进程控制之system函数
ISO C定义了system函数,但是其操作对系统的依赖性很强。POSIX.1包括了system接口,它扩展了ISO C定义,以描述system在POSIX.1环境中的运行行为。
#include <stdlib.h>
int system( const char *cmdstring );
如果cmdstring是一个空指针,则仅当命令处理程序可用时,system返回非0值,这一特征可以确定在一个给定的操作系统上是否支持system函数。在UNIX中,system总是可用的。
因为system在其实现中调用了fork、exec和waitpid,因此有三种返回值:
(1)如果fork失败或者waitpid返回除EINTR之外的出错,则system返回-1,并且在errno中设置相应的错误类型值。
(2)如果exec失败(表示不能执行shell),则其返回值如同shell执行了exit(127)一样。
(3)否则所有三个函数(fork、exec和waitpid)都执行成功,并且system的返回值是shell的终止状态,其格式已在waipid中说明(参见http://www.cnblogs.com/nufangrensheng/p/3510101.html)。
程序清单8-12 system函数(没有信号处理)
[root@localhost apue]# cat system_nosighandling.c
#include <sys/wait.h>
#include <errno.h>
#include <unistd.h> int
system(const char *cmdstring) /* version without signal handling */
{
pid_t pid;
int status; if (cmdstring == NULL)
return(1); /* always a command processor with UNIX */ if ((pid = fork()) < 0)
{
status = -1; /* probably out of processes */
}
else if (pid == 0) /* child */
{
/*
* execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
* _exit(127); /* execl error */
* 此处程序原来是如上面所示,但我无法理解这里的逻辑(感觉是有问题的,但是执行也可获得正确结果)
* 改为了下面的形式
*/
if (execl("/bin/sh", "sh", "-c", cmdstring, (char *)0) < 0)
{
_exit(127); /* execl error */
}
}
else /* parent */
{
while (waitpid(pid, &status, 0) < 0)
{
if (errno != EINTR)
{
status = -1; /* error other than EINTR from waitpid() */
break;
}
}
} return(status);
}
shell的-c选项告诉shell程序取下一个命令行参数(在这里是cmdstring)作为命令输入(而不是标准输入或从一个给定的文件中读命令)。shell对以null字符终止的命令字符串进行语法分析,将它们分成命令行参数(如果不使用shell执行此命令,而是试图由我们自己去执行它,那么将相当困难)。传递给shell的实际命令字符串可以包含任一有效的shell命令。
注意,我们调用_exit而不是exit。这是为了防止任一标准I/O缓冲区(这些缓冲区会在fork中由父进程复制给子进程,详情请参考:http://www.cnblogs.com/nufangrensheng/p/3509492.html)在子进程中被冲洗。
程序清单8-13 调用system函数
[root@localhost apue]# cat prog8-13.c
#include "apue.h"
#include <sys/wait.h> int
main(void)
{
int status; if ((status = system("date")) < 0)
err_sys("system() error");
pr_exit(status); if ((status = system("nosuchcommand")) < 0)
err_sys("system() error");
pr_exit(status); if ((status = system("who; exit 44")) < 0)
err_sys("system() error");
pr_exit(status); exit(0);
}
运行程序清单8-13得到:
[root@localhost apue]# ./prog8-13
Wed Jan 8 23:06:53 PST 2014
normal termination, exit status = 0 对于date
sh: nosuchcommand: command not found
normal termination, exit status = 127 对于无此种命令
root pts/0 2014-01-03 22:57 (:0.0)
normal termination, exit status = 44 对于exit
使用system而不是直接使用fork和exec的优点是:system进行了所需的各种出错处理,以及各种信号处理(在带信号处理的system版本中)。
设置用户ID程序
如果在一个设置用户ID程序中调用system,那么会发生什么呢?这是一个安全性方面的漏洞,决不应当这样做。
如果一个进程正以特殊的权限(设置用户ID或设置组ID)运行,它又想生成另一个进程执行另一个程序,则它应当直接使用fork和exec,而且在fork之后、exec之前要改回到普通权限。设置用户ID或设置组ID程序决不应调用system函数。
本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/。
进程控制之system函数的更多相关文章
- 进程控制之fork函数
一个现有进程可以调用fork函数创建一个新进程. #include <unistd.h> pid_t fork( void ); 返回值:子进程中返回0,父进程中返回子进程ID,出错返回- ...
- 进程控制之exec函数
用fork函数创建子进程后,子进程往往要调用一种exec函数以执行另一个程序.当进程调用一种exec函数时,该进程执行的程序完全替换为新程序,而新程序则从其main函数开始执行.因为调用exec并不创 ...
- 二十六、Linux 进程与信号---system 函数 和进程状态切换
26.1 system 函数 26.1.1 函数说明 system(执行shell 命令)相关函数 fork,execve,waitpid,popen #include <stdlib.h> ...
- UNIX环境编程学习笔记(22)——进程管理之system 函数执行命令行字符串
lienhua342014-10-15 ISO C 定义了 system 函数,用于在程序中执行一个命令字符串.其声明如下, #include <stdlib.h> int system( ...
- Linux系统编程_8_进程控制之fork_wait_waitpid函数
fork函数: #include <unistd.h> pid_t fork(void); fork用来创建一个子进程: 特点: fork调用后会返回两次,子进程返回0,父进 ...
- linux c编程:进程控制(三)_exec函数
fork()函数通过系统调用创建一个与原来进程(父进程)几乎完全相同的进程(子进程是父进程的副本,它将获得父进程数据空间.堆.栈等资源的副本.注意,子进程持有的是上述存储空间的“副本”,这意味着父子进 ...
- 进程控制之exit函数
进程有下面5种正常终止方式: (1)在main函数内执行return语句.这等效于调用exit. (2)调用exit函数.此函数有ISO C定义,其操作包括调用各终止处理程序(终止处理程序在调用ate ...
- 进程控制之waitid函数
Single UNIX Specification的XSI扩展包括了另一个取进程终止状态的函数--waitid,此函数类似于waitpid,但提供了更多的灵活性. #include <sys/w ...
- 进程控制之vfork函数
vfork函数的调用序列和返回值与fork相同,但两者的语义不同. vfork用于创建一个新进程,而新进程的目的是exec一个新程序.vfork和fork一样都创建一个子进程,但是它并不将父进程的地址 ...
随机推荐
- hdu4561 bjfu1270 最大子段积
就是最大子段和的变体.最大子段和只要一个数组,记录前i个里的最大子段和在f[i]里就行了,但是最大子段积因为有负乘负得正这一点,所以还需要把前i个里的最小子段积存起来.就可以了.直接上代码: /* * ...
- 新版本ubuntu13.10软件安装
问题1:如何解决ubunt13.04不能和主机共享文件的问题 . 安装VMware Tools 网上有很多的资料,这里没有给出. . 设置共享文件夹目录 ) 在VMware虚拟机窗口,选择VM-> ...
- VS中使用QT调用R脚本
一开始想直接把R编译成库然后调用R,后来查了n多资料,发现VS中是无法办到的,官方也给出了一句话,大概意思就是没可能在VS中使用R提供的C++接口,大概是涉及到了底层的ABI的原因,具体也不太清楚. ...
- (四面体)CCPC网络赛 HDU5839 Special Tetrahedron
CCPC网络赛 HDU5839 Special Tetrahedron 题意:n个点,选四个出来组成四面体,要符合四面体至少四条边相等,若四条边相等则剩下两条边不相邻,求个数 思路:枚举四面体上一条线 ...
- 产品设计敏感度之kindle touch 4
这种训练方法来自于<嵌入式系统开发之道:菜鸟成长日志与项目经理的私房菜>,名字真够长的,但是里面都是干货,我虽然之前有短评这本书,但是后面看完之后会继续再做一个详细的感悟记录. 选出身边的 ...
- elasticsearch配置文件解析
配置es的集群名称 : cluster.name: fcz_es
- android 源码编译中的错误 解决
1.编译种错误提示: arm-none-linux-gnueabi-gcc: directory: No such file or directory arm-none-linux-gnueabi-g ...
- Spring For Android初体验
Spring For Android是Spring框架的一个扩展,其主要目的在乎简化Android本地应用的开发,这其中包括了你可以使用该项目提供的 RestTemplate来为你的Android客户 ...
- 第二百九十、一、二天 how can I 坚持
上周日,腊八,好冷,去菏泽了.坐火车,没座.好冷,下午菏泽学院,大体看了看,很是怀念,有点遗憾,在网吧玩的时间太长了,留不住. 周一,长太婚礼,竟然没有只是吃了个饭,有点小失望,下午坐车回京,两点坐的 ...
- VB.NET开发中遇到的一点小问题
在用vb.net开发的security support时,遇到一个问题,在trainingCourses.aspx页面上增加了一个HyperLink控件 <asp:HyperLink runat ...