Linux -- system函数学习记录
Linux C编程中,调用另一个可执行文件或调用命令可以使用system函数和exec系列的函数。下面关于system函数的一些方法和使用做一个简单的记录。system在程序中执行一个命令字符串很方便,在man system的时候,可以看到#include <stdlib.h>int system(const char *command);system()通过调用/...
Linux C编程中,调用另一个可执行文件或调用命令可以使用system函数和exec系列的函数。
下面关于system函数的一些方法和使用做一个简单的记录。
system在程序中执行一个命令字符串很方便,在man system的时候,可以看到
#include <stdlib.h>
int system(const char *command);
system()通过调用/bin/sh -c命令执行命令中指定的命令,并在命令完成后返回。在执行命令期间,SIGCHLD将被阻塞,SIGINT和SIGQUIT将被忽略。
阻塞:就是忙完再说
忽略:收到了但是没有任何动作
比如在当前路径下,存在一个名为 a.out 的可执行文件,那么在一个进程main中使用system来执行这个a.out的程序,则可以直接使用
sysRet = system("./a.out");
system是在其实现中调用了fork + exec + waitpid, 执行完毕之后,回到原先的程序中去。继续执行下面的部分。
至于system的返回值
1、如果command是一个空指针,则仅当命令处理程序可用时,system返回非0值。可是使用这一个特性测试当前系统是否支持system函数,UNIX中总是可用的。
2、如果fork失败或者waitpid返回除EINTR之外的出错,返回-1,且设置errno。
3、如果exec失败(即不能执行shell),返回值如同shell实行了exit(127)一样。
4、如果fork,exec,waitpid都执行成功,那返回值是shell的终止状态,可以参见waitpid的说明使用system而不直接使用fork和exec的优点是:system进行了所需的各种出错的处理以及各种信号的处理
可以看到system的实现代码为:
#include <sys/wait.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
int system(const char *cmdstring)
{
pid_t pid;
int status;
struct sigaction ignore,saveintr,savequit;
sigset_t chldmask, savemask;
if(cmdstring == NULL)
return(1); /* always a command processor with UNIX */
ignore.sa_handler = SIG_IGN; /* ignore SIGINT and SIGQUIT */
sigemptyset(&ignore.sa_mask);
ignore.sa_flags = 0;
if(sigaction(SIGINT,&ignore,&saveintr) < 0)
return(-1);
if(sigaction(SIGQUIT,&ignore,&savequit) < 0)
return(-1);
sigemptyset(&chldmask); /*now block SIGCHLD*/
sigaddset(&chldmask,SIGCHLD);
if(sigprocmask(SIG_BLOCK,&chldmask,&savemask) < 0)
return(-1);
if((pid = fork()) < 0)
status = -1; /* probably out of processes*/
else if(pid == 0 ){ /* child */
/* restore previous signal action & reset signal mask*/
sigaction(SIGINT,&saveintr,NULL);
sigaction(SIGQUIT,&savequit,NULL);
sigprocmask(SIG_SETMASK,&savemask,NULL);
execl("/bin/sh","sh","-c",cmdstring,(char *)0);
_exit(127); /*exec error */
}else{ /*parent*/
while(waitpid(pid,&status,0) < 0){
if(errno != EINTR){
status = -1; /* error other than EINTR from waitpid() */
break;
}
}
}
/*restore previous signal actions & reset signal mask*/
if(sigaction(SIGINT,&saveintr,NULL) < 0)
return(-1);
if(sigaction(SIGQUIT,&savequit,NULL) < 0)
return(-1);
if(sigprocmask(SIG_SETMASK,&savemask,NULL) < 0)
return(-1);
return(status);
}
几个system的简单使用:
1、调用系统命令,打印出当前目录下的所有文件和文件夹。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
int ret = 1;
if(argc >= 2) printf("argv[1] = %s\r\n", argv[1]);
else printf("argv[0] = %s\r\n", argv[0]);
ret = system("ls -a");
printf("ret = %d, Byebye...\r\n");
return 0;
}
上面的代码文件名称为system1.c,编译生成可执行文件为system1
运行时候没有传入命令行参数,可以看到运行结果,列出了当前目录下的所有的文件(夹)
2、由一个程序调用另外一个程序(以调用上面的一个程序为例,不传入命令行参数)
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
int ret = 1;
ret = system("./system1");
printf("ret = %d\r\n", ret);
return 0;
}
上面的代码文件名称为system2.c,编译生成可执行文件为system2
直接运行system2,可以看到运行结果,成功的调用了程序system1,列出了当前目录下的所有的文件(夹),并且成功返回0
3、由一个程序调用另外一个程序(以调用上面的一个程序为例,传入命令行参数)
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
int ret = 1;
ret = system("./system1 args");
printf("ret = %d\r\n", ret);
return 0;
}
重新生成可执行文件system2,可以看到运行结果,成功的调用了程序system1,列出了当前目录下的所有的文件(夹),成功的传递命令行参数args,并且成功返回0
4、那么对于另外一种情况,如果两个程序是无限循环执行的
那么在采用的system调用另外一个无线循环的程序的时候,可以看到,调用者和被调用者都是运行的状态中,可以参见
点我就是哦!
更多推荐
所有评论(0)