1.fork()函数
#include<unistd.h>
pid_t fork(void);
创建一个子进程。
正确返回:父进程中返回子进程的进程号;子进程中返回0;(返回两次,父进程和子进程中各返回一次)
错误返回:-1;(父进程中返回)
2.vfork()函数
#include<unistd.h>
pid_t vfork(void);
创建一个子进程,阻塞父进程。vfork创建新进程的主要目的在于用exec函数执行另外的程序。
返回情况同fork()函数。
fork,vfork区别:
(1)fork()的子进程拷贝父进程的数据段,代码段;vfork()的子进程与父进程共享数据段。
(2)fork()后父、子进程的执行顺序不确定;vfork()后,子进程先运行(阻塞父进程),在调用exec或exit之前与父进程数据是共享的,在它调用exec或exit之后父进程才运行。
(3) vfork()保证子进程先运行,在她调用exec或exit之后父进程才可能被调度运行。如果在调用这两个函数之前子进程、 依赖于父进程的进一步动作,则会导致死锁。
注意1:主要是第3点难以理解,我理解是:在vfork()子进程执行的代码,必须调用execX函数或者以exit、_exit函数结束,否则会发生错误。(具体原因望大牛指点……在网上找了好多,没有人给予解答。)
注意2:vfork()后从子进程中返回,必须使用_exit()函数来返回,如果使用exit()或者return的时候,会关闭所有的IO,此时如果父进程再进行IO操作,就会出错。
实例:
#include <unistd.h> #include <stdio.h> int main() { pid_t pid; int count = 0; pid = vfork(); ++count; printf("count = %d\n",count); return 0; }
如果是fork(),结果很容易知道,是:
count = 1
count = 1
是调用vfork()呢,结果出人意料的是:
count = 1
count = 2
count = 1
count = 2…… //直到进程号被分配完才会退出。
3.system函数
#include<stdlib.h>
int system(constchar *command);
执行一个shell命令。
我们直接看system函数的实现代码:int system(const char *cmd) { pid_t pid; int status; if(cmd == NULL) { return 1; } if((pid = fork()) < 0) { status = -1; } else if(pid == 0) { execl("/bin/sh", "sh", "-c",cmd, (char*)0); _exit(127); } else { while(waitpid(pid, &status, 0) < 0) { if(errno != EINTR) { status = -1; break; } } } return status; }可见, system() 函数调用 fork() 创建子进程,然后调用 execl() 函数覆盖子进程镜像去执行 shell 命令 “cmd” ,父进程一直在阻塞等待子进程的返回。
fork的一道面试题:
#include <unistd.h> #include <stdio.h> int main() { int i; for(i = 0; i < 2; ++i) { fork(); printf("-"); } return 0; }
问打印多少“-”?
答案:在fork()的调用处,整个父进程空间会原模原样地复制到子进程中,包括指令,变量值,程序调用栈,环境变量,缓冲区等。printf(“-”);把“-”放到了缓存中,并没有真正的输出,在fork的时候,缓存被复制到了子进程空间,所以,就多了两个,就成了8个,而不是6个。如果printf("-\n");有“\n”时,是每次刷新缓冲区,这样最后打印6个,因为标准输出遇到“\n”,或是EOF,或是缓中区满,或是文件描述符关闭,或是主动flush,或是程序退出,就会把数据刷出缓冲区。
求解:
不得不说vfork真的很蛋疼,一些现象我是实在理解不了,如下:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> int createproc(); int main() { printf("main : pid = %d\n",getpid()); pid_t pid = createproc(); printf("in main : %d\n", pid); exit(0); } int createproc() { pid_t pid; if((pid = vfork()) == 0) { printf("child proc:%d,id = %d\n", pid,getpid()); return pid; } else if(pid > 0) { printf("parent run, child pid = %d\n",pid); return pid; } else return -1; }
out:
main : pid = 3416
child proc:0,id = 3417
in main : 0
parent run, child pid = 3417
child proc:0,id = 3418
//最后一句理解不了,懂的人还望留言指点