01.popen
是标准c提供的一个管道创建函数,其内部操作主要是创建一个管道,调用fork创建子进程,关闭不需用的文件描述符,调用exec函数族执行popen的第一个参数。然后等到关闭。
#include “stdio.h”
FILE *popen( const char* command, const char* mode )
参数说明:
command: 是一个指向以 NULL 结束的 shell 命令字符串的指针。
这行命令将被传到 bin/sh 并使用 -c 标志,shell 将执行这个命令。
mode: 只能是读或者写中的一种,得到的返回值(标准 I/O 流)也
具有和 type 相应的只读或只写类型。如果 type 是 “r” 则文件指针连接到 command 的标准输出;
如果 type 是 “w” 则文件指针连接到command 的标准输入。
返回值:
如果调用成功,则返回一个读或者打开文件的指针,如果失败,
返回NULL,具体错误要根据errno判断
注意:
- popen() 函数用创建管道的方式启动一个 进程, 并调用 shell. 因为管道是被定义成单向的, 所以 type 参数只能定义成只读或者只写, 不能是两者同时, 结果流也相应的是只读或者只写。
- popen() 函数的返回值是一个普通的标准I/O流, 它只能用 pclose() 函数来关闭, 而不是 fclose() 函数. 向这个流的写入被转化为对 command 命令的标准输入; 而 command 命令的标准输出则是和调用popen()函数的进程相同,除非这个被command命令自己改变. 相反的, 读取一个 “被popen了的” 流, 就相当于读取command 命令的标准输出, 而 command 的标准输入则是和调用 popen函数的进程相同。
02.system
system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略。
#include<stdlib.h>
int system(const char * string);
返回值:
=-1:出现错误
=0:调用成功但是没有出现子进程
>0:成功退出的子进程的id
如果system()在调用/bin/sh时失败则返回127,其他失败原因返回-1。若参数string为空指针(NULL),则返回非零值。
如果system()调用成功则最后会返回执行shell命令后的返回值,但是此返回值也有可能为 system()调用/bin/sh失败所返回的127,因此最好能再检查errno 来确认执行成功。
注意:
在编写具有SUID/SGID权限的程序时请勿使用system(),system()会继承环境变量,通过环境变量可能会造成系统安全的问题。
实际上system()函数执行了三步操作:
1.fork一个子进程;
2.在子进程中调用exec函数去执行command;
3.在父进程中调用wait去等待子进程结束。