1.system()
#include <stdlib.h>
int system(const char *command);
函数描述:
system() executes a command specified in command by calling /bin/sh -c command, and returns after the command has been completed. Dur‐ing execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored.
大概意思就是system()函数是通过调用/bin/sh -c来执行命令的,/bin/sh一般是一个软链接,用来指向某一个具体的shell,在command执行期间,SIGCHLD将会处于阻塞状态,SIGINT和SIGQUIT信号会被忽略
command 参数 是一个字符串指针, 指向的是一个 以 null 结束符 结尾的字符串, 这个字符串包含 一个 shell 命令. 这个命令 被送到 /bin/sh 以 -c 参数 执行, 即由 shell 来执行.
system()执行过程:
- fork一个子进程
- 在子进程中调用exec函数使子进程执行command
- 父进程调用wait等待子进程的退出
源码:
int system(const char * cmdstring)
{
pid_t pid;
int status;
if(cmdstring == NULL)
{
return (1); //如果cmdstring为空,返回非零值,一般为1
}
if((pid = fork())<0)
{
status = -1; //fork失败,返回-1
}
else if(pid == 0)
{
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
_exit(127); // exec执行失败返回127
}
else //父进程
{
while(waitpid(pid, &status, 0) < 0)
{
if(errno != EINTR)
{
status = -1; //如果waitpid被信号中断,则返回-1
break;
}
}
}
return status; //如果waitpid成功,则返回子进程的返回状态
}
通过源码不难看出system()函数的返回值:
如果fork失败,则返回-1。
如果exec执行成功,也就是command顺利执行,则返回command通过exit或return返回的值。
如果exec执行失败,也就是command没有顺利执行,比如被信号中断,或者command命令根本不存在,则返回127.
如果command为NULL,则system()函数返回非0值,一般为1.
2.popen()
#include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
函数描述:
popen()函数首先和system()函数相同,通过调用fork()创建一个子进程,通过/bin/sh -c来执行command。另外,popen()函数还会创建一个管道用于父进程和子进程之间的通信,这个管道是单向的,由popen()函数的type参数决定,“r”代表父进程从管道读取数据,“w”代表父进程向管道写入数据。
返回值:若成功则返回文件指针,否则返回NULL,错误原因存于errno中
pclose()用来关闭由popen所建立的管道及文件指针。参数stream为先前由popen()所返回的文件指针
返回值:若成功返回shell的终止状态(也即子进程的终止状态),若出错返回-1,错误原因存于errno中
用代码实现读功能:
1 #include<stdio.h>
2 #include<stdlib.h>
3
4 int main() {
5 FILE* fp=popen("cat test.txt","r");
6 char buf[1024];
7 if(fp == NULL) {
8 perror("popen error\n");
9 exit(1);
10 }
11 while(fgets(buf,1024,fp)!=NULL){
12 printf("%s",buf);
13 }
14 fclose(fp);
15 return 0;
16 }
运行结果: