1.创建一个进程
进程是系统中基本的执行单位(线程是最小的调度单位)。
linux系统允许任何一个用户创建一个子进程,创建之后,子进程存于系统之中,并且独立于父进程。该子进程可以接受调度,可以分配得到系统资源。
fork函数创建一个新的进程:
#include
pid_t fork(void);
注:系统中,除了0号进程以外(0号进程是由系统创建的),任何一个进程都是由其他进程创建的。
fork()函数不需要参数,返回一个进程ID。返回值有三种情况:
(1)对于父进程,fork函数返回新的子进程的ID。
(2)对于子进程,fork函数返回0。
(3)如果出错,fork函数返回-1。
fork函数创建一个新的进程,并从内核中为此进程得到一个新的可用进程ID,之后为这个新进程分配进程空间,并将父进程的进程空间中的内容复制到子进程的进程空间中,包括父进程的数据段+堆栈段,并与父进程共享代码段。
fork函数之后,子进程从等待fork返回开始执行,而不是从头开始。
2.父子进程的共享资源
子进程完全复制了父进程的地址空间的内容,包括堆栈段+数据段的内容。但是,子进程并没有复制代码段,而是和父进程共享代码段。代码段是只读的,不存在修改的问题,因此可以共用。
3.创建一个共享父进程空间的子进程
在创建一个子进程后,子进程的地址空间完全和父进程分开,父子进程是两个独立的进程。接受系统调度和分配系统资源的机会均等。父子进程完全分家,除了代码段这部分。
linux环境下提供一个和fork函数类似的函数,可以用来创建一个共用父进程地址空间的子进程。
pid_t vfork();
vfork()与fork()的区别:
(1)vfork产生的子进程和父进程完全共享地址空间,包括代码段+数据段+堆栈段。子进程对共享资源进行的修改,也会影响到父进程。
(2)vfork函数产生的子进程一定比父进程先运行。即父进程调用了vfork函数后会等待子进程运行后再运行。
4.在函数内部调用vfork函数
- #include <stdio.h>
- #include <unistd.h>
- int f1()
- {
- vfork(); //create child process
- return 0;
- }
- int f2(int a,int b)
- {
- return a+b;
- }
- int main()
- {
- int c;
- f1();
-
- c=f2(1,2);
- printf("%d\n",c);
- return 0;
- }
上面的代码在f1函数中调用了vfork函数。
父进程在调用f1函数后,子进程先执行,所以子进程从f1中返回,由于栈共享,f1函数的栈帧随着子进程的执行被覆盖掉。子进程调用f2也没有错误。但当父进程从f1中返回时,f1()的栈帧已经被f2()覆盖了。所以父进程返回错误。
5.退出进程
linux环境下使用exit()函数退出
#include
void exit(int status);
exit()函数的参数表示退出的状态,这个状态的值是一个整型。在shell中可以检查到这个退出的状态值。
- #include <stdlib.h>
- int main()
- {
- exit(2);
- }
- #echo $?
- #2
return语句会被翻译成调用exit函数。
可以将errno变量作为参数返回。
exit(errno)。
阅读(5401) | 评论(0) | 转发(2) |