fork()函数通过复制调用进程来创建一个新的进程。
格式为:
#include <unistd.h>
pid_t fork(void);
返回值类型:
若调用失败,返回值为0;
若调用成功,返回给父进程以子进程的进程号,返回给子进程0;
即,可以通过返回值类型的不同,将父进程的处理过程和子进程的处理过程写在同一个文件中。
fork()函数过程:操作系统先创建一个进程描述块,然后把父进程的所有进程描述符的信息精确拷贝过来,和父进程一样(除了进程ID不一样外),代码段共享,数据段和堆栈段复制,所有的寄存器的值全部精确拷贝,文件描述符也许精确拷贝。
父进程和子进程的不同之处如下:
原文:
* The child has its own unique process ID, and this PID does not match
the ID of any existing process group (setpgid(2)).
* The child's parent process ID is the same as the parent's process
ID.
* The child does not inherit its parent's memory locks (mlock(2),
mlockall(2)).
* Process resource utilizations (getrusage(2)) and CPU time counters
(times(2)) are reset to zero in the child.
* The child's set of pending signals is initially empty (sigpend‐
ing(2)).
* The child does not inherit semaphore adjustments from its parent
(semop(2)).
* The child does not inherit record locks from its parent (fcntl(2)).
* The child does not inherit timers from its parent (setitimer(2),
alarm(2), timer_create(2)).
* The child does not inherit outstanding asynchronous I/O operations
from its parent (aio_read(3), aio_write(3)), nor does it inherit any
asynchronous I/O contexts from its parent (see io_setup(2)).
1. 子进程的进程号不同与父进程;
2. 子进程的挂起信号集为空;
3. 子进程不继承父进程的计时器;
4. 子进程不继承父进程的异步I/O操作和环境。
即,当一个进程调用了fork以后,系统会创建一个子进程。这个子进程和父进程不同的地方只有他的进程ID和父进程ID不同,其他的都是一样。就象进程克隆(clone)自己一样。一旦子进程被创建,父子进程一起从fork处继续执行,相互竞争系统的资源。
代码如下:#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
int main()
{
pid_t pid;
pid=fork();
switch(pid)
{
//fork调用失败
case -1:
perror("fork error");
exit(1);
//子进程的fork返回值
case 0:
printf("this is child process\n");
printf("my pid is %d\n", getpid());
printf("my parent pid is %d\n", getppid());
break;
default:
printf("this is parent process\n");
printf("my pid is %d\n", getpid());
printf("my child process pid is %d\n", pid);
break;
}
}
执行结果:
this is parent process
my pid is 3675
my child process pid is 3676
this is child process
my pid is 3676
my parent pid is 1
注意子进程的父进程PID为1,原因在于子进程执行时,父进程已经执行结束而退出,所以子进程会自动把父进程PID改为1;
在调试状态下,或子进程先执行的情况下,不会出现该问题。