system()函数功能强大,很多人用却对它的原理知之甚少先看linux版system函数的源码:

 #include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <unistd.h> int system(const char * cmdstring)
{
pid_t pid;
int status; if(cmdstring == NULL){
return ();
} if((pid = fork())<){
status = -;
} else if(pid = ){
execl("/bin/sh", "sh", "-c", cmdstring, (char *));
exit(); //子进程正常执行则不会执行此语句
} else{
while(waitpid(pid, &status, ) < ){
if(errno != EINTER){
status = -;
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一返回主函数还是没变。原因从system的实现可以看到,它是通过产生新进程实现的,从我的分析中可以看到父进程和子进程间没有进程通信,子进程自然改变不了父进程的环境变量。

使用了system函数就能执行dos指令。

 #include <stdio.h>
#include <stdlib.h> xiaoyu()
{
char *a;
int n=;
FILE *f;
f=fopen("file.bat","w+");/*新建一个批处理*/
if(f==NULL) {
exit();
} a="echo"; /*DOS命令*/
for(n=;n<=;n++) {/*大写A-Z*/
fprintf(f,"%s %c\n",a,n);/*利用ASCII码输出A-Z,写出批处理*/
}
fclose(f);
system("file.bat");/*运行批处理*/
} int main(int argc, char argv[])
{
char *string; xiaoyu();
string="echo C语言的system函数\n";/*输出中文*/
system(string);
system("pause");/*程序暂停*/
return ;
}

C中可以使用DOS命令,以后编程通过调用DOS命令很多操作就简单多了。

转至:C语言中system()函数的用法总结

C语言中system()函数的用法总结(转)的更多相关文章

  1. C语言中sprintf()函数的用法

    sprintf函数的用法 1.该函数包含在stdio.h的头文件中. 2.sprintf和平时我们常用的printf函数的功能很相似.sprintf函数打印到字符串中,而printf函数打印输出到屏幕 ...

  2. C语言中strtod()函数的用法详解

    函数原型: #include <stdlib.h> double strtod(const char *nptr, char **endptr); C语言及C++中的重要函数. 名称含义 ...

  3. C语言中qsort函数用法

    C语言中qsort函数用法-示例分析    本文实例汇总介绍了C语言中qsort函数用法,包括针对各种数据类型参数的排序,非常具有实用价值非常具有实用价值. 分享给大家供大家参考.C语言中的qsort ...

  4. R语言中apply函数

    前言 刚开始接触R语言时,会听到各种的R语言使用技巧,其中最重要的一条就是不要用循环,效率特别低,要用向量计算代替循环计算. 那么,这是为什么呢?原因在于R的循环操作for和while,都是基于R语言 ...

  5. 使用C语言中qsort()函数对浮点型数组无法成功排序的问题

    一 写在开头 1.1 本节内容 本节主要内容是有关C语言中qsort()函数的探讨. 二 问题和相应解决方法 qsort()是C标准库中的一个通用的排序函数.它既能对整型数据进行排序也能对浮点型数据进 ...

  6. C语言中malloc函数返回值是否需要类型强制转换问题

    1. 在C语言中, 如果调用的函数没有函数原型, 则其返回值将默认为 int 型. 考虑调用malloc函数时忘记了 #include <stdlib.h>的情况 此时malloc函数返回 ...

  7. (转)C语言中Exit函数的使用

    C语言中Exit函数的使用 exit() 结束当前进程/当前程序/,在整个程序中,只要调用 exit ,就结束return() 是当前函数返回,当然如果是在主函数main, 自然也就结束当前进程了,如 ...

  8. C语言中malloc函数的理解

    在C语言中malloc函数主要是用在堆内存的申请上,使用malloc函数时,函数会返回一个void *类型的值,这个值就是你申请的堆内存的首地址:为什么返回的地址是一个void *类型的地址呢?首先我 ...

  9. 关于C语言中printf函数“输出歧视”的问题

    目录 关于C语言中printf函数"输出歧视"的问题 问题描述 探索问题原因 另一种研究方法 问题结论 关于C语言中printf函数"输出歧视"的问题 问题描述 ...

随机推荐

  1. iOS 两个App之间调起通信

    前言 假设需求是这样的:由一个app1跳转到app2之后,app2完成某项任务之后,怎么把app2的完成信息传到app1(自己的程序是app1),传的是什么类型的数据,怎么进行解析? 逻辑 本文章使用 ...

  2. ArrayBlockingQueue跟LinkedBlockingQueue的区别

    .队列中的锁的实现不同 ArrayBlockingQueue中的锁是没有分离的,即生产和消费用的是同一个锁: LinkedBlockingQueue中的锁是分离的,即生产用的是putLock,消费是t ...

  3. Samba配置

    https://wiki.samba.org/index.php/Samba_AD_DC_Port_Usage 安装后开放端口 1    ACCEPT     tcp  --  0.0.0.0/0   ...

  4. iOS一些系统事件的生命周期

    1.- (void)applicationWillResignActive:(UIApplication *)application 说明:当应用程序将要入非活动状态执行,在此期间,应用程序不接收消息 ...

  5. Linux配置SSH免密码登陆

    配置环境: 两台centos 6.4虚拟机,/etc/hosts配置如下 192.168.63.128 hadoop001 --master192.168.63.131 hadoop002 --sla ...

  6. impdp报错: ORA-39064: 无法写入日志文件 ORA-29285: 文件写入错误

    windows平台下,oracle 11.2.0.1在使用impdp向测试环境导入数据的时候,报出如下错误: 错误原因: 数据泵在写日志文件的时候,使用的是数据库字符集.如果客户端的环境变量NLS_L ...

  7. GIS简单计算Helper类

    using System; using ESRI.ArcGIS.Client.Geometry; namespace GISProject.Extensions { /// <summary&g ...

  8. winform 计算器

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  9. 从出租车司机到大BOSS的转型之路

    来深圳之前,曾有人这样告诉我:在深圳千万不能以貌取人,打扮不起眼,也许他转身开的座驾就是宝马.奔驰;不管一个人多么邋遢俗气,也别瞧不起人家,也许他的手提袋里就是成捆的人民币现金;不管一个人打扮的多么土 ...

  10. android 加载大图片

    引用:http://my.eoe.cn/littlebirds/archive/4646.html 尽量不要使用setImageBitmap或setImageResource或BitmapFactor ...