为了简化执行命令的复杂程度,Linux系统提供system
系统调用,原理是通过fork
的方式产生一个子进程,在这个子进程中执行系统调用过程中参数里面设定的command
。
system函数
#include <stdlib.h>
int system(const char *command);
功能:
利用fork
创建子进程,然后用execl来执行/bin/sh sh -c command
指令。system
函数的主进程必须等待子进程执行完后再退出,并返回执行状态。
参数:
command
:需要执行的命令的字符串,比如需要查看当前目录下的文件信息,则将command
设定为ls -l
。
返回值:
-
出现异常时返回
-1
; -
子进程正常退出,返回
0
或者其他值。
实际上system()函数执行了三步操作:
-
fork一个子进程;
-
在子进程中调用
exec
函数去执行command
; -
在父进程中调用
wait
去等待子进程结束。对于fork失败,system
()函数返回-1。如果exec
执行成功,则返回command
通过exit
或return
返回的值。
函数源码:
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 != EINTER){
status = -1;
break;
}
}
}
return status;
}
实例:
编程要求
在主函数的最开始会初始化一个全部变量g_i4event
为0
。
本关的编程任务是补全右侧代码片段中Begin
至End
中间的代码,具体要求如下:
-
执行“touch test.dat”命令;
-
检查命令是否执行成功,如果执行成功,则将
g_i4event
设为1
; -
执行成功返回
0
,执行失败返回-1
。
测试样例:
测试输入:
预期输出:touch ./test.dat successful!
system command executed successful!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
#include <dirent.h>
pthread_t pid;
int g_i4event = 0;
int do_system(void);
int do_system(void)
{
/********Begin********/
if(system("touch test.dat")!=-1)
{
g_i4event=1;
return 0;
}
return -1;
/*********End*********/
}
void *detect(void *arg)
{
int count = 0;
while (1)
{
if(access("./test.dat", F_OK))
{
count ++;
}
switch(g_i4event)
{
case 0:
break;
case 1:
count ++;
if(1 == count)
{
printf("system command executed successful!\n");
}
return NULL;
default:
break;
}
g_i4event = 0;
usleep(10 * 1000);
}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_create(&pid, NULL, detect, NULL);
if(0 == do_system())
{
printf("touch ./test.dat successful!\n");
}
else
{
printf("touch ./test.dat failed!\n");
}
pthread_join(pid, NULL);
return 0;
}