LINUX fork的使用

fork函数

#include<stdio.h>
#include<unistd.h>
int main()
{
	int count=0;
	pid_t pid;
	pid= fork();
	//进程在执行fork时一分为2,且有两个返回值。两个进程依次执行if else
	if(pid>0)
	{
		printf("我是爸爸,fork返回值=%d,进程号=%d,父进程号=%d\n",pid,getpid(),getppid());
		//进程在执行fork时一分为2,且有两个返回值。两个进程依次执行if else
		count++;
	}
	else if(pid==0)
	{
		printf("我是儿子,fork返回值=%d,进程号=%d,父进程号=%d\n",pid,getpid(),getppid());
		//如果上面的父进程没结束,该进程的父进程号为上面的进程号,结束了之后,该进程的父进程号变为init进程号
		count++;
	}
	else if(pid<0)
	{
		printf("出错,fork返回值=%d,进程号=%d\n",pid,getpid());
	}
	printf("count = %d\n",count);
	return 0;
}
执行结果:

我是爸爸,fork返回值=15749,进程号=15748,父进程号=14852
count = 1
我是儿子,fork返回值=0,进程号=15749,父进程号=15748
count = 1

fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
    1)在父进程中,fork返回新创建子进程的进程ID;
    2)在子进程中,fork返回0;
    3)如果出现错误,fork返回一个负值;

 引用一位网友的话来解释fpid的值为什么在父子进程中不同。“其实就相当于链表,进程形成了链表,父进程的fpid(p 意味point)指向子进程的进程id,

fork出错可能有两种原因:
    1)当前的进程数已经达到了系统规定的上限,这时errno的值被设置为EAGAIN。
    2)系统内存不足,这时errno的值被设置为ENOMEM。

创建新进程成功后,系统中出现两个基本完全相同的进程,这两个进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。
    每个进程都有一个独特(互不相同)的进程标识符(process ID),可以通过getpid()函数获得,还有一个记录父进程pid的变量,可以通过getppid()函数获得变量的值。

 执行完fork后,进程1的变量为count=0,fpid!=0(父进程)。进程2的变量为count=0,fpid=0(子进程),这两个进程的变量都是独立的,

可以发现两个count都是1,这是因为在fork之后,子进程将代码复制了一份,继续往下执行,两个人都有一个count,各自加的各自的count。

进阶:

#include<stdio.h>
#include<unistd.h>
int main()
{
	int i=0;

	for(i=0;i<2;i++)
	{
		pid_t fpid=fork();
		if(fpid>0)
			printf("%d parent %4d %4d %4d\n",i,getppid(),getpid(),fpid);
		else if(fpid==0)
			printf("%d child %4d %4d %4d\n",i,getppid(),getpid(),fpid);
	}
	return 0;
}
该函数执行6次printf,产生了3个新进程。第一次循环产生一个子进程,第二次循环时,父子进程都执行,都产生一个新进程。

i值   父或子(相对)  父进程号    当前进程号  fork返回值

0 child 15842 15843    0

0 parent 14852 15842 15843
1 parent 14852 15842 15845
1 parent 1311 15843 15844
1 child 1311 15844    0
1 child 1311 15845    0

大家可以执行下面的程序看看

int main() {  
	pid_t fpid;
	printf("fork!\n");
	//printf("fork!");
fpid = fork();if (fpid < 0) printf("error in fork!"); else if (fpid == 0) printf("I am the child process, my process id is %d\n", getpid()); else printf("I am the parent process, my process id is %d\n", getpid()); }


第一个printf加了换行符,则输出是

fork!
I am the parent process, my process id is 16728
I am the child process, my process id is 16729

不加换行符,输出是

fork!I am the parent process, my process id is 16739
fork!I am the child process, my process id is 16740

 这就跟printf的缓冲机制有关了,printf某些内容时,操作系统仅仅是把该内容放到了stdout的缓冲队列里了,并没有实际的写到屏幕上。

但是,只要看到有/n 则会立即刷新stdout,因此就马上能够打印了。
    运行了printf("fork!")后,“fork!”仅仅被放到了缓冲里,程序运行到fork时缓冲里面的“fork!”  被子进程复制过去了。因此在子进程度stdout

缓冲里面就也有了fork! 。所以,你最终看到的会是fork!  被printf了2次!!!!
    而运行printf("fork! /n")后,“fork!”被立即打印到了屏幕上,之后fork到的子进程里的stdout缓冲里不会有fork! 内容。因此你看到的结果会是fork! 被printf了1次!!!!
    所以说printf("+");不能正确地反应进程的数量。

fork之后夫子进程除非采用了同步手段,否则不能确定谁先运行,也不能确定谁先结束。认为子进程结束后父进程才从fork返回的,这是不对的,fork不是这样的,vfork才这样。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值