system()函数exec函数簇popen()函数
若果还须要获取返回结果,有两种较简单便捷的方式
popen()函数匿名管线1.system()函数
所需头文件:#include
函数原型:intsystem(constchar*cmdstring);
cmdstring是一个字符表针,就是一个包含须要运行的shell命令的字符串
通过查阅《UNIX环境中级编程》,以下是system函数的一种实现方法
int system(const char *cmdstring)
{
pid_t pid;
int status;
if (cmdstring == NULL)
{
return (1);
}
if ((pid = fork()) < 0)
{
status = -1;
}
else if (pid == 0)
{
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
_exit(127);
}
else
{
while (waitpid(pid, &status, 0) < 0)
{
if (errno != EINTR)
{
status = -1;
break;
}
}
}

return(status);
}
返回值:
注:exec失败或则shell命令执行失败,返回值会填入返回的整形状态status的8~15位,0~7位全为0,所以exit(127)的结果为32512是将127换成二补码为1111111,填入status的8~15位,则为0000,换成十补码就是32512
通过以下对程序的试验,个人得出推论linux命令详解词典,命令正确执行返回0,不太肯定所有的命令linux运行c程序,尝试了mv,cp,touch,ls命令正确返回都为0;exec执行失败,多半是没这个命令,返回32512;若果是其他正整数,代表shell命令是有的,但shell命令执行出问题linux运行c程序,比如右图ls一个没有的文件,返回512.
#include
int main()
{
int ret = 0;
ret = system(NULL);
printf("ret = %d n",ret);//ret = 1
return 0;
}
#include
int main()
{
int ret = 0;
ret = system("exit 55");
printf("ret = %d n",ret);//ret = 14080
return 0;
}
#include
int main()
{
int ret = 0;
ret = system("ls dsfgsdfg");//ls一个没有的文件 ret = 512
printf("ret = %d n",ret);
return 0;
}
#include
int main()
{
int ret = 0;

ret = system("asdfgdsgs");//输入一个没有的命令 ret = 32512
printf("ret = %d n",ret);
return 0;
}
#include
int main()
{
int ret = 0;
ret = system("ls");
printf("ret = %d n",ret);//正常 ret = 0
return 0;
}
2.exec函数簇
我就直接照抄我的文章《linux编程进程与线程基本实例》里的exec函数簇介绍了。
调用exec函数时,该调用ecec的进程执行的程序完全替换为新程序,但并不创建新进程,前后进程的ID并不改变。exec只是用c盘上的一个新程序替换了当前进程的正文段、数据段、堆段和栈段。
#include
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char * const envp[]);
最后一个参数为NULL或则(char*)0
成功不会返回任何值,调用失败会返回-1
constchar*path要写绝对路径,constchar*file就不用
比如execlp(“ls”,”ls”,”-l”,NULL);
execl(“/bin/ls”,”ls”,”-l”,NULL);
char*arg[]={“ls”,”-a”,NULL}
execv(“/bin/ls”,arg);
execvp(“ls”,arg);
3.popen()函数和pclose()函数
常见操作是创建一个联接到另一个进程(shell的命令行)的管线android linux,之后读其输出或向其输入端发送数据。
工作原理:popen先执行fork,之后调用exec执行cmdstring,并返回一个标准的I/O文件表针。
头文件:#include
原型:FILE*popen(constchar*cmdstring,constchar*type)
cmdstring:包含shell命令字符串
type:为”r”时,则文件表针联接到cmdstring的标准输出,也就是代表指向执行shell命令返回的消息,也可以觉得链接到stdout
为”w”时,则文件表针联接到cmdstring的标准输入,也可以觉得链接到stdin
intpclose(FILE*fp);
fp:为ponen返回的文件表针
返回值:成功返回cmdstring的中止状态;出错返回-1
下边是执行通过popen函数执行shell命令ls的代码
#include
int main()
{
FILE *fp = NULL;
char data[100] = {'0'};
fp = popen("ls", "r");
if (fp == NULL)
{
printf("popen error!n");
return 1;
}
while (fgets(data, sizeof(data), fp) != NULL)
{
printf("%s", data);
}
pclose(fp);
return 0;
}
4.匿名管线pipe
使用管线来获取执行shell命令返回的信息,通常流程如下
1.创建管线
2.使用dup函数复制描述符将shell命令行标准输出绑定到管线的写端
3.从管线的读端读取数据
pipe函数
所需头文件:#include
函数原型:intpipe(intfd[2]);
返回值:成功返回0,出错返回-1
一个反例:创建进程,创建匿名管线,子进程使用dup2函数将标准输出的描述符复制给管线的写端,父进程从管线的读端读取数据
#include
#include
#include
#include
int main()
{
int fpipe[2] = {0};
pid_t fpid;
char massage[1000] = {0};
memset(massage, 0, 20);
if (pipe(fpipe) 0)
{
wait(NULL);
printf("this is father,recieve:");
fflush(stdout);
close(fpipe[1]);
read(fpipe[0], massage, 1000);
printf("%sn",massage);
}
else
{
printf("create fork error!n");
}
return 0;
}