popen/system函数与fork函数的区别

本文详细比较了popen和system函数的功能与使用场景。介绍了这两个函数如何在shell中执行命令,包括它们的参数传递方式、返回值的意义及执行流程上的区别。特别指出popen允许并行执行,而system则采用串行方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

popen函数:
#include <stdio.h>

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

int pclose(FILE *stream);
函数说明:

popen()函数:首先,调用fork()函数创建一个子进程,执行一个shell命令,其次,调用pipe()函数创建一个管道,与子进程进行通讯。这个子进程必须由pclose()函数关闭,pclose()函数用于关闭标准I/O流,等待命令执行结束,然后返回shell的终止状态,如果shell不能被执行,则pclose()函数返回的终止状态与shell已执行exit一样。

command:是一个指向将要在shell中执行的命令的C风格字符串的指针,这个命令将被传到bin/sh并使用-c标志执行。

type:只能是读或写的一种,得到的返回值(标准I/O流)也具有和type相应的类型,如果type为”r”,那么返回的文件指针连接到command的标准输出,如果type为”w”,那么返回的文件指针连接到command的标准输入。

返回值:如果调用fork()或pipe()失败,或者不能分配内存函数将返回NULL,否则返回标准I/O流。这个返回的流是基于pipe()创建的管道实现的,是单向的,所以,当这个流是输入流时,向流中写内容相当于写入该命令的标准输入,此时,命令的标准输出和调用popen的进程相同。当这个流是输出流时,从流中读出数据相当于读取命令的标准输出,此时,命令的标准输入与调用popen的进程相同。

返回错误: popen没有为内存分配失败设置errno值。如果调用fork或pipe失败,errno将被设置成相应的错误类型。如果type参数不合法,errno将返回EINVAL。


system函数:
#include <stdlib.h>

int system(const char *command);
函数说明:

system()会调用fork()产生子进程,由子进程调用exec()执行shell命令,此命令执行完后随即返回原调用的进程,在调用system()期间,SIGCHLD会被暂时屏蔽,SIGINT、SIGQUIT信号则会被忽略。

command:是一个指向将要在shell中执行的命令的C风格字符串的指针,这个命令将被传到bin/sh并使用-c标志执行。

返回值:如果fork()失败,返回-1,出现错误。如果exec()失败,表示不能执行shell,返回值相当于shell执行了exit,返回127。如果执行成功则返回子shell的终止状态。

附加说明:在编写具有SUID/SGID权限的程序时请勿使用system(),system()会继承环境变量,通过环境变量可能会造成系统安全的问题。


fork函数:

fork()函数读者可参考我的另一篇博客,链接如下:
Linux下fork()&vfork()的区别、getenv()&setenv()函数以及僵尸进程、孤儿进程讲解


区别:
执行流程:

system调用进程会一直等待shell命令执行完成拿到shell返回状态才继续执行,popen调用进程不用等待shell执行完成拿到shell返回状态便可执行,即system函数内部含有wait操作,而popen函数内部不含有wait操作,wait操作在pclose函数中执行。可以理解为system为串行执行、popen为并行执行。

信号处理:

system中会屏蔽SIGCHLD信号,到底为什么会屏蔽SIGCHLD信号呢???那是因为在system函数中内置有wait操作,当我们不屏蔽SIGCHLD信号时,system创建的子进程执行完成后,会激活信号处理函数,若此时在信号处理函数中调用wait函数,就会将子进程的资源释放掉,system中的wait函数便会调用失败,而规定system函数中需要返回shell的执行状态,所以应该屏蔽SIGCHLD信号。
popen中不用屏蔽SIGCHLD信号,是因为如果屏蔽SIGCHLD信号,若在popen和pclose中创建新进程的话,进程结束不会调用信号处理函数,此进程的回收工作会在pclose的wait操作中进行,而popen中的创建的进程将不会被回收,而不屏蔽的话,popen和pclose中创建的进程会在信号处理函数中回收,popen中创建的进程会在pclose中回收。所以不应该屏蔽SIGCHLD信号。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值