linux system函数使用详解

相关函数
fork,execv e,waitpid, popen
表头文件
#i nclude<std lib.h>
定义函数
int system(con st char * string);
函数说明
system()会调 fork()产生子进程,由子进程来调用 /bin/sh-c string来执行参 数string字符串 所代表的命令,此命> 执行完后随即返回调用的进程。在调用s ystem()期间 SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略。
返回值
=-1:出现错误 
=0:调用成功 
=1:入参字符串为空
=127:execl执行失败
如果system() 调用/bin/sh时失败则返回127其他失败原因返回-1 。若参数string 为空指针(NULL) ,则返回非零值1。
果system()调 用成功则最后会返回执 行shell命令后的 返回值,但是此返回值 也有可能为 system()调用 /bin/sh失败所 返回的127,因此最 好能再检查errno  来确认执行成功。
附加说明
在编写具有SUID/ SGID权限的程序时 请勿使用system (),system( )会继承环境变量,通 过环境变量可能会造成 系统安全的问题。
范例
#include<std lib.h>
main()
{
system(“ls  -al /etc/passw d /etc/shado w”);
}
执行结果:
-rw-r--r--  1 root root 705 Sep 3 13 :52 /etc/passw d
-r-------- - 1 root root 572 Sep 2 15 :34 /etc/shado
例2:
char tmp[];
sprintf(tm p,"/bin/mo unt -t vfat %s /mnt/usb", dev);
system(tmp );
其中dev是/dev /sda1。
 
system源码
#include
#include
#include
#include
int system(con st char * cmdstring)
{
       pid_t pid;
       int status;
       if(cmdstri ng == NULL){
               
                 return (1);
       }

       if((pid = fork())<0) {
                       status = -1;
       }
       else if(pid == 0){
               execl("/bi n/sh", "sh", "-c", cmdstring,  (char *)0);
               -exit(127) ; //子进程正常执行则 不会执行此语句
               }
       else{
                       while(wait pid(pid, &status, 0) < 0){
                               if(errno != EINTER){
                                       status = -1;
                                       break;
                               }
                       }
               }
               return status;
}
先分析一下原理,然后 再看上面的代码大家估 计就能看懂了: 
当system接受的 命令为NULL时直接 返回,否则fork出 一个子进程,因为fo rk出两个进程:父进 程和子进程中都返回, 这里要检查返回的pi d,fork在子进程 中返回0,在父进程中 返回子进程的pid, 父进程使用waitp id等待子进程结束, 子进程则是调用exe cl来启动一个程序代 替自己,execl( "/bin/sh",  "sh", "-c", cmdstring, (char*)0)是 调用shell,这个 shell的路径是/ bin/sh,后面的 字符串都是参数,然后 子进程就变成了一个s hell进程,这个s hell的参数是cm dstring,就是 system接受的参 数。
 
如果上面的你没有看懂 ,那我再解释下for k的原理:当一个进程 A调用fork时,系 统内核创建一个新的进 程B,并将A的内存映 像复制到B的进程空间 中,因为A和B是一样 的,那么他们怎么知道 自己是父进程还是子进 程呢,看fork的返 回值就知道,上面也说 了fork在子进程中 返回0,在父进程中返 回子进程的pid。
execl是编译器的 函数(在一定程度上隐 藏具体系统实现),在 linux中它会接着 产生一个linux系 统的调用execve , 原型见下:
       int execve(con st char * file,const  char **argv,con st char **envp);
 
看到这里你就会明白为 什么system() 会接受父进程的环境变 量,但是用syste m改变环境变量后,s ystem一返回主函 数还是没变,原因从s ystem的实现可以 看到,它是通过产生新 进程实现的,从我的分 析中可以看到父进程和 子进程间没有进程通信 ,子进程自然改变不了 父进程的环境变量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值