Linux下C程序执⾏shell命令并获取返回结果的⽅法Linux下的C编程有以下⼏种⽅法可以执⾏shell命令
1. system()函数
2. exec函数簇
3. popen()函数
如果还需要获取返回结果,有两种较简单⽅便的⽅法
1. popen()函数
2. 匿名管道
1.system()函数
所需头⽂件:#include<stdlib.h>
函数原型:int system(const char *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);
}
返回值:
如果cmdstring字符指针为NULL,返回1
如果fork失败或者waitpid返回除EINTR之外的错,则返回-1
如果exec失败,即不能执⾏shell(多半是没这个命令),返回值如同shell执⾏了exit(127)⼀样,结果为32512
如果fork、exec、waitpid都没有问题,shell也有这个命令,那么返回值是shell的终⽌状态(即执⾏shell命令的返回值)
注:exec失败或者shell命令执⾏失败,返回值会填⼊返回的整形状态status的8~15位,0~7位全为0,所以exit(127)的结果为32512是将127换成⼆进制为1111111,填⼊status的8~15位,则为111111100000000,换成⼗进制就是32512
通过以下对程序的试验,个⼈得出结论,命令正确执⾏返回0,不太肯定所有的命令,尝试了mv,cp,touch,ls命令正确返回都为0;exec执⾏失败,多半是没这个命令,返回32512;如果是其他正整数,代表shell命令是有的,但shell命令执⾏出问题,例如下图ls⼀个没有的⽂件,返回512.
#include<stdio.h>
int main()
{
int ret = 0;
ret = system(NULL);
printf("ret = %d \n",ret);//ret = 1
return 0;
}
#include<stdio.h>
int main()
{
int ret = 0;
ret = system("exit 55");
printf("ret = %d \n",ret);//ret = 14080
return 0;
}
#include<stdio.h>
int main()
{
int ret = 0;
ret = system("ls dsfgsdfg");//ls⼀个没有的⽂件  ret = 512
printf("ret = %d \n",ret);
return 0;
}
#include<stdio.h>
int main()
{
int ret = 0;
ret = system("asdfgdsgs");//输⼊⼀个没有的命令 ret = 32512
printf("ret = %d \n",ret);
return 0;
}
#include<stdio.h>
int main()
{
int ret = 0;
ret = system("ls");
printf("ret = %d \n",ret);//正常  ret = 0
return 0;
}
<函数簇
我就直接照搬我的⽂章《》⾥的exec函数簇介绍了。
调⽤exec函数时,该调⽤ecec的进程执⾏的程序完全替换为新程序,但并不创建新进程,前后进程的ID并不改变。exec只是⽤磁盘上的⼀个新程序替换了当前进程的正⽂段、数据段、堆段和栈段。
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
const char *path要写绝对路径,const char *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的命令⾏)的管道,然后读其输出或向其输⼊端发送数据。
⼯作原理:popen先执⾏fork,然后调⽤exec执⾏cmdstring,并返回⼀个标准的I/O⽂件指针。
头⽂件:#include<stdio.h>
原型:FILE *popen(const char *cmdstring, const char *type)
cmdstring:包含shell命令字符串
type:为”r”时,则⽂件指针连接到cmdstring的标准输出,也就是代表指向执⾏shell命令返回的消息,也可以认为链接到stdout            为”w”时,则⽂件指针连接到cmdstring的标准输⼊,也可以认为链接到stdin
int pclose(FILE *fp);
fp:为ponen返回的⽂件指针
返回值:成功返回cmdstring的终⽌状态;出错返回-1
下⾯是执⾏通过popen函数执⾏shell命令ls的代码
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<unistd.h>
函数原型:int pipe(int fd[2]);
返回值:成功返回0,出错返回-1
⼀个例⼦:创建进程,创建匿名管道,⼦进程使⽤dup2函数将标准输出的描述符复制给管道的写端,⽗进程从管道的读端读取数据
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
int main()
{
int fpipe[2] = {0};
pid_t fpid;
char massage[1000] = {0};
memset(massage, 0, 20);
if (pipe(fpipe) < 0)
{
printf("Create pipe error!\n"); }
fpid = fork();
if (fpid == 0)
{
close(fpipe[0]);
dup2(fpipe[1],STDOUT_FILENO);  system("ls");
shell代码
}
else if (fpid > 0)
{
wait(NULL);
printf("this is father,recieve:");
fflush(stdout);
close(fpipe[1]);
read(fpipe[0], massage, 1000);  printf("%s\n",massage);
}
else
{
printf("create fork error!\n");
}
return 0;
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。