2019独角兽企业重金招聘Python工程师标准>>>

system()函数功能强大,很多人用却对它的原理知之甚少,也就有了上面那么多的回帖,我想大家如果知道了 system的具体实现就不会对楼主程序在很多编译器中不能表现自己希望的功能感到费解了。我对linux中的实现比较了解,具体分析这个,windows中的类似就不详解了。

好了,先看linux版system函数的源码:

代码:

#include
#include
#include
#include

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;
}

先分析一下原理,然后再看上面的代码大家估计就能看懂了:

当system接受的命令为NULL时直接返回,否则fork出一个子进程,因为fork在两个进程:父进程和子进程中都返回,这里要检查返回的 pid,fork在子进程中返回0,在父进程中返回子进程的pid,父进程使用waitpid等待子进程结束,子进程则是调用execl来启动一个程序代替自己,execl("/bin/sh", "sh", "-c", cmdstring,(char*)0)是调用shell,这个shell的路径是/bin/sh,后面的字符串都是参数,然后子进程就变成了一个 shell进程,这个shell的参数是cmdstring,就是system接受的参数。在windows中的shell是command,想必大家很熟悉shell接受命令之后做的事了。
  
如果上面的你没有看懂,那我再解释下fork的原理:当一个进程A调用fork时,系统内核创建一个新的进程B,并将A的内存映像复制到B的进程空间中,因为A和B是一样的,那么他们怎么知道自己是父进程还是子进程呢,看fork的返回值就知道,上面也说了fork在子进程中返回0,在父进程中返回子进程的pid。

windows中的情况也类似,就是execl换了个又臭又长的名字,参数名也换的看了让人发晕的,我在MSDN中找到了原型,给大家看看:

HINSTANCE   ShellExecute(
          HWND   hwnd,
          LPCTSTR   lpVerb,
          LPCTSTR   lpFile,
          LPCTSTR   lpParameters,
          LPCTSTR   lpDirectory,
          INT   nShowCmd
  );

用法如下: 
  ShellExecute(NULL,   "open",   "c:\\a.reg",   NULL,   NULL,   SW_SHOWNORMAL);

你也许会奇怪 ShellExecute中有个用来传递父进程环境变量的参数 lpDirectory,linux中的execl却没有,这是因为execl是编译器的函数(在一定程度上隐藏具体系统实现),在linux中它会接着产生一个linux系统的调用execve, 原型见下:
  int execve(const char * file,const char **argv,const char **envp);
  
看到这里你就会明白为什么system()会接受父进程的环境变量,但是用system改变环境变量后,system一返回主函数还是没变,这就是我在 22楼反复强调的。原因从system的实现可以看到,它是通过产生新进程实现的,从我的分析中可以看到父进程和子进程间没有进程通信,子进程自然改变不了父进程的环境变量。希望小菜们不要拿tc或使用tc库的其他编译器中的system的调用结果来反驳我,这不是一个概念,DOS早死翘翘了,玩 linux吧。就说到这里了。

system(执行shell 命令)
相关函数
      fork,execve,waitpid,popen
表头文件
      #include<stdlib.h>
定义函数
      int system(const char * string);
函数说明
      system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略。
返回值
      如果system()在调用/bin/sh时失败则返回127,其他失败原因返回-1。若参数string为空指针(NULL),则返回非零值。如果 system()调用成功则最后会返回执行shell命令后的返回值,但是此返回值也有可能为system()调用/bin/sh失败所返回的127,因此最好能再检查errno 来确认执行成功。
附加说明
      在编写具有SUID/SGID权限的程序时请勿使用system(),system()会继承环境变量,通过环境变量可能会造成系统安全的问题。

如果system调用的命令成功执行,则返回0;
如果是一个无法识别的命令,则返回的是一个非零值,我猜测好像是它的Pid;
其它的可以自己再测测!

转载于:https://my.oschina.net/u/2546684/blog/672131

system()函数实现相关推荐

  1. Linux下使用system()函数一定要谨慎

    转载自:http://my.oschina.net/renhc/blog/53580 linux尽量避免使用system. 曾经的曾经,被system()函数折磨过,之所以这样,是因为对system( ...

  2. linux windows c system 函数简介

    windows 在windows下的system函数中命令可以不区别大小写!  功 能: 发出一个DOS命令 #include <stdlib.h>int system(char *com ...

  3. 使用system函数时应该忽略两个信号

    在8.13节,我们展示了一个system函数的实现.然而,那个版本没有处理信号.POSIX.1要求system忽略 SIGINT和SIGQUIT并阻塞SIGCHLD.在展示正确处理这些信号的版本之前, ...

  4. 如何隐藏system函数的窗口

    如何隐藏system函数的窗口 修改浏览权限 | 删除 由于一直在写控制台的程序,对于MFC并不是很熟.这次写osg<-->ive格式转换器这个小工具的时候,涉及到使用setlocale函 ...

  5. system函数用法

    system函数用法 system函数 是可以调用一些DOS命令,比如 system("cls");//清屏,等于在DOS上使用cls命令. system函数是执行shell命令, ...

  6. linux:exec族函数, exec族函数配合fork使用,system 函数,popen 函数

    1.exec族函数 精彩博文: https://blog.csdn.net/u014530704/article/details/73848573 ​ ​ ​ path:   比如说 ./a.out ...

  7. C语言system函数(C语言程序中执行命令行)

    需包含头文件:C 标准库 - <stdlib.h> 文章目录 描述 声明 参数 返回值 实例1 实例2:列出 windows 机上当前目录下所有的文件和目录 描述 C 库函数 int sy ...

  8. system函数和fork-exec机制

    system函数 使用man system查看帮助如下: NAMEsystem -execute a shell commandSYNOPSIS#include<stdlib.h>ints ...

  9. linux下system函数的深入理解

    这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以为 ...

最新文章

  1. 聊天软交互原理_来自不同城市的人们如何在freeCodeCamp聊天室中进行交互
  2. 无需额外数据,首次实现ImageNet 87.1% 精度,颜水成团队开源VOLO
  3. Openldap/ldap 双向同步/复制/Mastsr/slave
  4. wk一sm5时间温度控制器_新能源汽车电机控制器温度计算及其模型—DC电容篇
  5. 微信朋友圈,QQ空间,微博等列表展示的功能实现
  6. conda环境下如何升级python?
  7. document.ready和onload的区别——JavaScript文档加载完成事件
  8. intx update task - IB_IBINTX_UPDATE
  9. makex机器人程序_收藏!MakeX 机器人挑战赛2018全球最新赛程和赛事手册公布
  10. js 数组(Array)
  11. 让你一周变聪明的大脑保健操
  12. lumen 项目根目录_利用rewrite修改网站根目录,适用于laravel、lumen
  13. 计算机知识培训感言,计算机培训的心得体会
  14. IE6下css常见bug处理
  15. 大学计算机vb基础知识6,西华师范大学计算机VB试题及答案6
  16. HTML上划线 中划线 下划线实现
  17. REUSE_ALV_GRID_DISPLAY_LVC 实现单元格值改变前(DATA_CHANGED)和单元格值改变后(DATA_CHANGED_FINISHED)的事件响应
  18. 10月16日上午MySQL数据库作业设计表解析
  19. HTML作业-商城网页
  20. Rosserial Arduino Library中从一行代码开始探究系统原理

热门文章

  1. SpringMVC+Apache Shiro+JPA(hibernate)案例教学(二)
  2. apache+svn
  3. Codeup 墓地——问题 B: A+B
  4. webstorm配置ESLint 一直
  5. 卓越的TurboGate邮件网关企业邮箱的安全保障
  6. 终于恢复了珍惜多年的照片
  7. 使用 Fries 创建性感的 Android 风格移动应用界面
  8. Follow Me:CCIE RS--新版CCIE Routing Switching 考纲要点
  9. PHP中array_merge和array相加的区别分析
  10. 别的设计师比你又快又好,是因为你不知道他们在用介个!