【Linux】利用fork()创建多个线程

在《【Linux】fork()》(点击打开链接)只是简单交代了如同利用fork()创建子线程的方法,实际是更应该说将一个程序一分为二的方法。还有很多事情隐藏在其中值得细致思考。由于fork()结构的特殊性,如果要用fork()创建多个线程,并不像pthread_create()那样轻松,而且最关键的一点,是你利用for循环和fork()创建出来的多线程,会不明不白地多出N条线程。这主要是由于对fork()的理解不够所造成的。比如如下代码:

#include <stdio.h>
int main(){ 
	pid_t pid[2]; 
	int i;
	for(i=0;i<2;i++){
		if((pid[i]=fork())<0){ 
			printf("Fork() Error!"); 
		} 
		else if(pid[i]==0){
			printf("This is parent %d,child is %d\n",getppid(),getpid());
		}
		else{
			wait(5); 
		}
	}
	return 0; 
}

看起来好像没有任何问题,创建2条子线程,就是在原有fork()的基础上,建立一个for而已。

但就是不知道会创建出4条线程。那是因为,问题没有想象中的那样简单,父进程现在标号为i=1的循环中创了一个子进程,然后第二次循环,前边的第一个子线程又创建一个子进程,这时明显系统中有四个进程。如下图所示:


因此这种创建多个子进程的方式不可取,是否一定需要用pthread_create呢?其实并不是,可以用如下的结构,创建多个子进程,以要创建4个为例:

#include <stdio.h>
#define MAX_THREAD 4//设置子线程数量
int main(){
	int i,status,pid;
	for(i=0;i<MAX_THREAD;i++){			
		status=fork();
		if (status==0||status ==-1){
			break;
			/*每次循环时,
			如果发现是子进程就直接从创建子进程的循环中跳出来,
			不让你进入循环,
			这样就保证了每次只有父进程来做循环创建子进程的工作
			*/
		}
	}	
	if(status==-1){//一般不会这种情况!
		printf("创建的子进程,失败");
	}
	else if(status==0){//每个子进程都会执行的代码
		printf("子线程id=%d,我老爸的id=%d,i=%d\n",getpid(),getppid(),i);
		wait(status,NULL,0);
	}
	else{
		printf("父进程id=%d\n",getpid());   
		while((pid=wait(&status))>0){ 
			printf("终结id为%d的子线程\n", pid); 
		}
	}	  
	return 0;
}

大家需要自己的子进程做什么,直接在else if(status==0){}这个结构里面改就行了。

同时,注意到这里停止子进程与《【Linux】fork()》(点击打开链接)停止单个子进程是不通。父进程一般不做任何事情,相当于pthread_create里面的主函数,具体见《【Linux】线程》(点击打开链接),他唯一的职责就是让等待每一个子线程停止。

运行结果如下图:


大家注意到这个运行结果很有意思,i是从3到0倒着来输出的。本身程序就很有意思,if-else if-else这个结构就游离在for循环之外,却如同将这段代码做了4次。

这是因为fork()保存现场,将线程压入栈的特性。i=0时候这个现场被创建的子线程最先入栈,所以他是最后输出的。

if-else if-else这个结构相当于将线程栈里面的线程经过else if中的处理之后一一出栈。

else if中最初能操作的东西,是子线程入栈时候的状态。

大家明白了吗,其实这跟汇编语言里面的循环其实很类似的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值