fork,vfork,system

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

//最后一句理解不了,懂的人还望留言指点





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值