说明:
本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。
QQ 群 号:513683159 【相互学习】
内容来源:
《Linux系统编程》、《Linux网络编程》、《Unix环境高级编程》
system()函数
一、函数介绍:
1.函数功能:同步的创建进程,即:进程创建新进程后立刻开始等待它结束。【依赖操作系统】
一般用来运行简单的工具程序或shell脚本,并得到对应的返回值。
调用“/bin/sh-c command
”执行特定命令,阻塞当前进程command命令执行完毕。
项目 | 说明 |
---|---|
函数原型 | int system(const char *command); |
头文件 | stdlib.h |
参数说明 | command:shell命令行指令 |
返回值 | 成功则返回执行命令状态(可用WEXITSTATUS得到) 失败则返回-1,并设置errno(fork失败或waitpid返回除EINTR外的错误). sh不能执行则返回127(exec失败) |
注意 | ①若command是NULL且/bin/sh可用,则返回非零值,其他情况返回0 ②执行该函数时,会调用fork、execve、waitpid等函数,若其中任一失败则该函数调用失败 ③在命令执行的过程中,SIGCHILD信号是被阻塞的,而且 SIGINT和sIGQUIT信号会被忽略。 ④若进程正以特殊权限运行(设置用户ID/设置组ID),又想生成另一进程执行另一程序则应使用fork().exec().且exec()之前需改回普通权限。 |
2.函数实现:实现中调用fork()、exec()、waitpid()
。
二、示例实践:
(1)示例功能说明:
1.获取当前进程的ID并输出到屏幕上。
2.使用system()
函数进行系统调用ping某网址。
3.将system()
函数返回值输出到屏幕上。
(2)源程序:system.c
#include<stdlib.h>
#include<unistd.h>
int main(int argc,char *argv[])
{
int ret = 0;
printf("系统分配的进程号是:%d\n",getpid());
ret = system("ping www.baidu.com -c 2");
printf("返回值:%d\n",ret);
return 0;
}
(3)编译并运行:
①编译程序:gcc system.c -o system
②运行程序:./system
(4)运行结果
系统分配的进程号是:4425
PING www.a.shifen.com (220.181.38.150) 56(84) bytes of data.
64 bytes from 220.181.38.150: icmp_seq=1 ttl=128 time=43.0 ms
64 bytes from 220.181.38.150: icmp_seq=2 ttl=128 time=43.2 ms
--- www.a.shifen.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 43.071/43.169/43.267/0.098 ms
返回值:0
三、对SIGINT
和SIGQUIT
信号的忽略
实现对SIGINT
和SIGQUIT
信号的忽略有好几种实现方式,特别是当system()
在循环中被调用的时候。如果在一个循环中调用system()
,那么你需要保证子进程的退出状态要被正确检测。例如:
do {
int ret;
ret = system ("pidof rudderd" ) ;
if(wIFSIGNALED (ret) & &( WTERMSIG (ret) ==SIGINT llwTERMSIG (ret) == sIGQUIT))
break; /* or otherwise handle */
}while (1);
四、实现system()函数
利用fork()
、exec系列
、waitpid()
实现system()
函数。
/*
my_system -同步生成并等待命令
"/ bin/sh -c <cmd>"
任何类型的错误,或启动进程的退出码返回-1。不阻断或忽略任何信号。
*/
int my_system (const char *cmd)
{
int status;
pid_t pid;
pid = fork ( );
if (pid == -1)
return -l;
else if (pid -= 0)
{
const char *argv[ 4];
argv[ 0] ="sh" ;
argv[ 1] =“-c";
argv[ 2] = cmd;
argv[ 3] = NULL;
execv ("/bin/sh" ,argv) ;
exit (-1);
}
if( waitpid (pid, &status,0)== -1)
return -l;
else if (WIFEXITED (status))
return WEXITSTATUS (status);
return -l;
PS:
注意这个例子不像正式的system()
,它没有阻塞或者禁止任何信号。根据你程序的情况,这可能是好事也可能是坏事。但是至少要保证SIGINT
信号不被阻塞,这是很明智的,因为这样可以按照用户的意愿随时终止命令的执行。一个较好的实现可以将额外的指针做为参数,当参数为非空时,代表不同的错误。例如可能会加入fork_failed 和 shell failed。