Linux进程控制

封装fork/wait等操作, 编写函数 process_create(pid_t* pid, void* func, void* arg), func回调函数就是子进程执行的入口函数, arg是传递给func回调函数的参数.

#include<stdio.h>
#include<unistd.h>
void Func(char* arg){
	printf("%s,child is : %d   father is %d",arg,getpid(),getppid());
	sleep(5);
	return;
}
void process_creat(int* pid,void* Func,char* arg){
	pid_t id;
	*pid = fork();
	if (*pid<0){
		perror("");
		return;
	}
	//子进程
	else if (*pid==0){
		//因为Func为void* 类型的函数,所以首先要将Func()转化为(void(*)(char*))类型
		void(*p)(char*) = (void(*)(char*))Func;
		(*p)(arg);
	}
	else{
		//父进程阻塞等待
		id=waitpid(-1,NULL,0);
		printf("child wait success pid :%d",id);
		return;
	}
}
int main(){
	pid_t pid;
	process_creat(&pid,Func,"hello world");

}

popen:

#include <stdio.h>

       FILE *popen(const char *command, const char *type);

       int pclose(FILE *stream);

popen()函数通过创建一个管道,调用fork()产生一个子进程,执行一个shell以运行命令来开启一个进程。这个管道必须由pclose()函数关闭,而不是fclose()函数。pclose()函数关闭标准I/O流,等待命令执行结束,然后返回shell的终止状态。如果shell不能被执行,则pclose()返回的终止状态与shell已执行exit一样。

1.type参数只能是读或者写中的一种,得到的返回值(标准I/O流)也具有和type相应的只读或只写类型。如果type是"r"则文件指针连接到command的标准输出;如果type是"w"则文件指针连接到command的标准输入。

2.command参数是一个指向以NULL结束的shell命令字符串的指针。这行命令将被传到bin/sh并使用-c标志,shell将执行这个命令。

3. popen()的返回值是个标准I/O流,必须由pclose来终止。前面提到这个流是单向的(只能用于读或写)。向这个流写内容相当于写入该命令的标准输入,命令的标准输出和调用popen()的进程相同;与之相反的,从流中读数据相当于读取命令的标准输出,命令的标准输入和调用popen()的进程相同。

4.返回值:如果调用fork()或pipe()失败,或者不能分配内存将返回NULL,否则返回标准I/O流。popen()没有为内存分配失败设置errno值。如果调用fork()或pipe()时出现错误,errno被设为相应的错误类型。如果type参数不合法,errno将返回EINVAL。

​
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<string.h>
  4 int main(){
  5     FILE* fp=NULL;
  6     char buf[10240]={0};
  7     fp=popen("ls -al","r");
  8     if(fp==NULL){
  9         return -1;
 10     }
 11     fread(buf,10240,1,fp);
 12     printf("%s\n",buf);
 13     pclose(fp);
 14     return 0;
 15 }

​

缺点:使用popen的不好影响是,针对每个popen调用,不仅要启动一个被请求的程序,还要启动一个shell,即每个popen调用将多启动两个进程

system:

system()函数调用/bin/sh来执行参数指定的命令,/bin/sh 一般是一个软连接,指向某个具体的shell,比如bash,-c选项是告诉shell从字符串command中读取命令;在该command执行期间,SIGCHLD是被阻塞的,好比在说:hi,内核,这会不要给我送SIGCHLD信号,等我忙完再说;在该command执行期间,SIGINT和SIGQUIT是被忽略的,意思是进程收到这两个信号后没有任何动作

返回值:

为了更好的理解system()函数返回值,需要了解其执行过程,实际上system()函数执行了三步操作:

1.fork一个子进程;

2.在子进程中调用exec函数去执行command;

3.在父进程中调用wait去等待子进程结束。

对于fork失败,system()函数返回-1。

如果exec执行成功,也即command顺利执行完毕,则返回command通过exit或return返回的值

 1 int system(char* command){
  2     
  3     int pid;
  4     int status;
  5 
  6 if(command==NULL){
  7     
  8     //当command为空时返回非零值
  9     return 1;
 10     
 11 }
 12 if(pid=fork()<0){
 13     
 14     //创建子进程失败的话返回 -1;
 15     status=-1;
 16     
 17 }else if(pid=fork()==0){
 18     
 19     //exec函数足中的程序替换
 20     execl("/bin/sh","sh","-c",command,NULL);
 21     _exit(127);
 22 
 23 }else{
 24     
 25     //设置为阻塞状态
 26     while(waitpid(pid,&status,0)<0){
 27         if(errno!=EINTR ){
 28             status=-1;
 29             break;
 30         }
 31     }
 32 }
 33 
 34 return status;
 35 
 36 }

end;

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值