linux system 和 execl 函数对比

1. system()函数

1.1 system 函数的具体执行步骤

实际上,system也是调用了exec函数去执行一个系统命令,可以把system函数理解成对exec函数的一个包装

system函数的具体执行步骤是这样的:
1.fork一个子进程;
2.在子进程中调用exec函数去执行command;
3.在父进程中调用wait去等待子进程结束。
创建出一个子进程,然后在子进程中用exec来执行命令
创建出一个子进程,然后在子进程中用exec来执行命令,即是子进程成功执行了没返回也没关系,还有父进程可以返回嘛!
对于fork失败,system()函数返回-1。

如果exec执行成功,也即command顺利执行完毕,则返回command通过exit或return返回的值。

1.1.1 system 源码实现

int system(const char * cmdstring)
{
	pid_t pid;
	int status;
	if(cmdstring == NULL)
	{
		return (1); //如果cmdstring为空,返回非零值,一般为1
	}
	if((pid = fork())<0)
	{
		status = -1; //fork失败,返回-1
	}else if(pid == 0)
	{
		execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
		_exit(127); // exec执行失败返回127,注意exec只在失败时才返回现在的进程,成功的话现在的进程就不存在啦~~
	}else //父进程
	{
		while(waitpid(pid, &status, 0) < 0)
		{
			if(errno != EINTR)
			{
				status = -1; //如果waitpid被信号中断,则返回-1
				break;
			}
		}
	}

	return status; //如果waitpid成功,则返回子进程的返回状态
}

1.2 system 执行成功

#include <stdio.h>
#include <errno.h>

int main(int argc, char* argv[]){
	int a = system("/bin/ls -l");;
	printf("%d,errno=%d\n", a,errno);

	printf("exiting...\n");
	return 0;
}

结果:

[root@glusterfs home]# gcc sys.c -o sys
[root@glusterfs home]# ./sys 
total 32
-rwxr-xr-x 1 root root 8648 Dec  2 17:17 a.out
-rwxr-xr-x 1 root root 8648 Dec  2 17:32 sys
-rw-r--r-- 1 root root  195 Dec  2 17:31 sys.c
-rw-r--r-- 1 root root  307 Dec  2 17:17 test.c
0,errno=0
exiting...
[root@glusterfs home]#

1.3 system 执行成功,但命令未执行成功

#include <stdio.h>
#include <errno.h>

int main(int argc, char* argv[]){
	int a = system("/bin/rm 1.txt");;
	printf("%d,errno=%d\n", a,errno);

	printf("exiting...\n");
	return 0;
}

结果:

[root@glusterfs home]# gcc -o sys sys.c 
[root@glusterfs home]# ./sys 
/bin/rm: cannot remove ‘1.txt’: No such file or directory
256,errno=0
exiting...
[root@glusterfs home]#

1.4 system 执行成功,但命令执行失败

#include <stdio.h>
#include <errno.h>

int main(int argc, char* argv[]){
	int a = system("123 456");;
	printf("%d,errno=%d\n", a,errno);

	printf("exiting...\n");
	return 0;
}

结果:

[root@glusterfs home]# gcc -o sys sys.c 
[root@glusterfs home]# ./sys 
sh: 123: command not found
32512,errno=0
exiting...
[root@glusterfs home]#

2. execl 成功不会返回,命令执行失败返回-1

2.1 execl 执行成功不返回

原因:
在进程的创建上Unix采用了一个独特的方法,它将进程创建与加载一个新进程映象分离。
execl将当前进程替换掉,所有最后那条打印语句不会输出
利用execl将当前进程main替换掉,所有最后那条打印语句不会输出

2.1.1 exec 重要说明!!!

exec函数会取代执行它的进程, 也就是说, 一旦exec函数执行成功, 它就不会返回了, 进程结束.
但是如果exec函数执行失败, 它会返回失败的信息, 而且进程继续执行后面的代码!
通常exec会放在fork() 函数的子进程部分, 来替代子进程执行啦, 执行成功后子程序就会消失, 但是执行失败的话, 必须用exit()函数来让子进程退出!

#include <stdio.h>
int main(int argc, char* argv[]){

	int a = execl("/bin/ls", "ls", "-l", NULL);
	printf("%d\n", a);

	printf("exiting...\n");
	return 0;
}

root@glusterfs home]# gcc test.c 
[root@glusterfs home]# ll
total 16
-rwxr-xr-x 1 root root 8584 Dec  2 17:10 a.out
-rw-r--r-- 1 root root  175 Dec  2 17:10 test.c
[root@glusterfs home]# ./a.out 
total 16
-rwxr-xr-x 1 root root 8584 Dec  2 17:10 a.out
-rw-r--r-- 1 root root  175 Dec  2 17:10 test.c
[root@glusterfs home]# 

execl 执行后没有返回,没有打印代码中的值

2.1.2 execl + fork 返回信息

#include <stdio.h>
#include <errno.h>
#include <unistd.h>

int main(int argc, char* argv[]){
	int childpid;
	pid_t pid;

	pid = fork();
	if(pid > 0)
	{
		printf("parent execl done\n");
		wait(&childpid);
	}else if(0 == pid)
	{
		execl("/bin/ls", "ls", "-l", NULL);
		printf("pid execl done\n");
	}else{
		printf("error pid < 0 \n");
	}
	printf("exiting...\n");
	return 0;
}

结果:

[root@glusterfs home]# gcc test.c 
[root@glusterfs home]# ./a.out 
parent execl done
total 52
-rwxr-xr-x 1 root root 8632 Dec  3 14:14 a.out
-rw-r--r-- 1 root root  444 Dec  3 14:14 test.c
exiting...
[root@glusterfs home]#

2.2 execl 命令执行成功,内容失败,表示成功,不返回

执行成功的意思是这条命令本身没错,但是这条命令成不成功exec管不了,他只负责执行
比如说"rm 1.txt",这条指令是正确的,即使没有1.txt这个文件报了无法删除1.txt文件,exec函数还是算执行成功,不会有返回。

#include <stdio.h>

int main(int argc, char* argv[]){
	int a = execl("/bin/rm", "rm", "1.txt", NULL);
	printf("%d\n", a);

	printf("exiting...\n");
	return 0;
}

[root@glusterfs home]# gcc test.c 
[root@glusterfs home]# ./a.out 
rm: cannot remove ‘1.txt’: No such file or directory
[root@glusterfs home]#

2.3 execl 执行失败则直接返回-1,失败原因存于errno中

#include <stdio.h>
#include <errno.h>

int main(int argc, char* argv[]){
	int a = execl("hani", "1", "2", NULL);
	printf("%d,errno=%d\n", a,errno);

	printf("exiting...\n");
	return 0;
}

结果:

[root@glusterfs home]# gcc test.c 
[root@glusterfs home]# ./a.out 
-1,errno=2
exiting...
[root@glusterfs home]#

#define ENOENT 2 /* No such file or directory */

3. 总结:system 没有 exec 效率高

关于system 有一段这样的介绍: system 执行时内部会自动启用fork() 新建1个进程, 效率没有直接使用fork() 和 exec函数高.

参考:

https://www.cnblogs.com/Cccarl/p/6639089.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值