调研popen/system, 理解这两个函数和fork的区别.

. 调研popen/system, 理解这两个函数和fork的区别. :
system()函数
函数原型

#include <stdlib.h>
int system(const char *command);

system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略。
调用/bin/sh来执行参数指定的命令,/bin/sh 一般是一个软连接,指向某个具体的shell。

实际上system()函数执行了三步操作:
1.fork一个子进程;
2.在子进程中调用exec函数去执行command;
3.在父进程中调用wait去等待子进程结束。
返回值:
1>如果 exec 执行成功,即 command 顺利执行,则返回 command 通过 exit 或 return 的返回值。(注意 :command 顺利执行不代表执行成功,当参数中存在文件时,不论这个文件存不存在,command 都顺利执行)
2>如果exec执行失败,也即command没有顺利执行,比如被信号中断,或者command命令根本不存在, 返回 127
3>如果 command 为 NULL, 则 system 返回非 0 值.
4>对于fork失败,system()函数返回-1。
判断一个 system 函数调用 shell 脚本是否正常结束的方法的条件应该是
1. status != -1
2.(WIFEXITED(status) 非零且 WEXITSTATUS(status) == 0

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<string.h>
  5 int main(void)
  6 {
  7         int status=0;
  8         status=system("ls -l");
  9         if(status==-1){
 10                 perror("system()");
 11                 exit(1);}
 12         if(WIFEXITED(status)!=0)//正常退出{
 13                 if(WEXITSTATUS(status)==0)//操作正确{
 14                 printf("run command success\n");}
 15                 else{//操作错误
 16                         printf("run command fail and exit code is %d\n", WEXITSTATUS(status));
 17                 }
 18         }else//异常退出{
 19                 printf("exit code is  %d\n",  WEXITSTATUS(status));
 20         }
 21         return 0;
 22 }

这里写图片描述
popen()函数:创建一个管道用于进程间通信,并调用shell,因为管道被定义为单向的 所以 type 参数 只能定义成 只读或者 只写, 不能是 两者同时, 结果流也相应的 是只读 或者 只写.
函数原型:

  #include <stdio.h>

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

       int pclose(FILE *stream);

`
函数功能:popen()会调用fork()产生子进程,然后从子进程中调用/bin/sh -c来执行参数command的指令。这个进程必须由 pclose 关闭。

command参数:
command 参数 是 一个 字符串指针, 指向的是一个 以 null 结束符 结尾的字符串, 这个字符串包含 一个 shell 命令. 这个命令 被送到 /bin/sh 以 -c 参数 执行, 即由 shell 来执行.

type 参数 也是 一个 指向 以 null 结束符结尾的 字符串的指针
参数type可使用“r”代表读取,“w”代表写入。
依照此type值,popen()会建立管道连到子进程的标准输出设备或标准输入设备,然后返回一个文件指针。
随后进程便可利用此文件指针来读取子进程的输出设备或是写入到子进程的标准输入设备中。
返回值:
若成功则返回文件指针,否则返回NULL,错误原因存于errno中

 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 int main()
  5 {
  6          FILE * file = NULL;
  7         char buf[1024]={0};
  8         file=popen("cat hello.c","r");
  9         if(file==NULL){
 10         perror("popen()");
 11         exit(1);}
 12         while(fgets(buf,1024,file)!=NULL){
 13                  fprintf(stdout, "%s", buf); }
 14         pclose(file);
 15         return 0;
 16 }

结果为:
这里写图片描述

区别
1.system 在执行期间,调用进程会一直等待 shell 命令执行完成(waitpid),但是 popen 无需等待 shell 命令执行完成就返回了。可以理解为,system为串行执行,popen 为并行执行。
2.popen 函数执行完毕后必须调用 pclose 来对所创建的子进程进行回收,否则会造成僵尸进程的情况。
3.popen 没有屏蔽 SIGCHLD ,如果我们在调用时屏蔽了 SIGCHLD ,如果在 popen 和 pclose 之间调用进程又创建了其他子进程并调用进程注册了 SIGCHLD 来处理子进程的回收工作,那么这个回收工作会一直阻塞到 pclose 调用。

fork-popen和system都是用来创建进程函数fork函数是用于创建一个新的进程,新进程完全复制了父进程的资源。子进程可以通过返回值来区分自己是子进程还是父进程fork函数相当于同时调用了fork、exec和waitpid这三个系统调用,等待子进程执行完成后再继续执行。而popen函数则是通过管道来启动一个进程,并返回一个文件指针,可以用来读取或写入子进程的输入输出。popen函数不需要等待子进程执行完成就可以返回。 系统提供的system函数是用于执行shell命令的。它的原型是`int system(const char* command)`,可以通过传入shell命令作为参数来执行命令。system函数一直等待shell命令执行完成(waitpid),然后返回。而popen函数则可以并行执行shell命令,不需要等待命令执行完成。 在使用popen函数后,需要调用pclose来对所创建的子进程进行回收,否则可能导致僵尸进程的情况。 总结起来,fork-popen和system都是用来创建进程函数,但是fork-popen是并行执行的,而system是串行执行的。同时,在使用popen函数后,需要调用pclose进行子进程回收。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Linux---popen、system函数](https://blog.csdn.net/y6_xiamo/article/details/80156598)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [重新实现popen和system函数](https://download.csdn.net/download/u013105439/10441160)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值