system 和 exec 的区别

2024-06-09 21:12
文章标签 区别 system exec

本文主要是介绍system 和 exec 的区别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在 linux 中,使用 system 和 exec 都可以执行一个程序或者执行一个命令。两者的区别如下:

system 中创建了一个子进程,在子进程中执行用户的命令,子进程执行完毕之后,system 会返回。exec 不会创建子进程,而是直接用 exec 要执行的进程来代替当前的进程,并且如果在执行过程中没有出现错误,那么 exec 是不会返回的,调用 exec 的进程永远也回不来了。

1 exec

使用如下两个代码来演示 exec 的执行过程。

如下代码使用 gcc hello.c -o hello 来编译出可执行文件 hello。这段代码中每隔一秒中打印一次 hello,打印 3 次之后退出。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>int main() {int i = 0;while (i < 3) {printf("hello\n");sleep(1);i++;}return 0;
}

下边的代码中,main 函数中首先创建了一个线程,线程中每隔 1 秒打印一次 in thread。打印 5 次之后,调用 execv 来执行一个程序,第一次执行的程序是 hello1,是一个不存在的可执行文件,这种情况下, execv 会返回错误。第二次调用 execv 来执行 hello,hello 得到执行。

#include <iostream>
#include <thread>
#include <unistd.h>void thread_func() {while (1) {std::cout << "in thread\n";sleep(1);}
}int main() {std::thread t(thread_func);sleep(5);std::cout << "before wrong exec\n";int ret = execv("./hello1", NULL);if (ret < 0) {perror("exec error:");}std::cout << "after wrong exec\n";std::cout << "before right exec\n";execv("./hello", NULL);std::cout << "after right exec\n";return 0;
}

程序运行结果如下,从打印信息来看,可以得出如下 3 点:

(1)调用 exec 正确执行的时候,exec 执行的可执行文件覆盖了整个程序的镜像,不仅仅是 main 函数所在的主线程不执行了,main 函数中创建的子线程也不运行了,调用 exec 之后 in thread 不再打印

(2)exec 执行的程序 hello,打印 3 次 hello 之后退出,这个时候 exec 也不会返回了,after right exec 没有打印

(3)当 exec 找不到可执行文件时,会返回错误,并且设置了 errno,信息是 No such file or directory

2 system

将 execv 替换程 system,代码如下。

#include <iostream>
#include <thread>
#include <unistd.h>void thread_func() {while (1) {std::cout << "in thread\n";sleep(1);}
}int main() {std::thread t(thread_func);t.detach();sleep(5);std::cout << "before wrong system\n";int ret = system("./hello1");if (ret < 0) {perror("1 system error:");}std::cout << "after wrong system\n";std::cout << "before right system\n";ret = system("./hello");if (ret < 0) {perror("2 system error:");}std::cout << "after right system\n";return 0;
}

执行结果如下,从执行结果可以看出来:

(1)system 执行的时候只是阻塞当前这个线程的执行,并没有阻塞整个进程的执行, 在 system 执行的时候,main 函数中创建的 thread 还在运行,in thread 还在打印

(2)system 执行完毕之后,会返回,代码中的 after right system 打印了出来

3 popen

在软件开发中,有的时候有这样一个需求,就是在代码中执行一个命令,并且在代码中还可以获取到执行这个命令时的打印信息。比如在控制台,我们可以很容易的执行 free 命令来查看系统内存使用情况,如果我们想在代码中执行 free 命令,并且获取 free 命令的显示信息,最后把 free 显示的信息打印出来,应该怎么实现呢 ?可以通过 popen 来实现。

如下代码可以实现上述功能。popen 结合 fgets 可以获取到命令执行的打印信息,使用完毕之后要通过 pclose() 关闭句柄。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main() {FILE *fp;char buffer[1024];sleep(2);fp = popen("free", "r");if (fp == NULL) {printf("Error: Failed to run command\n");return EXIT_FAILURE;}while (fgets(buffer, sizeof(buffer), fp) != NULL) {printf("result:\n");printf("%s", buffer);}pclose(fp);return EXIT_SUCCESS;
}

为了使用 strace 来追踪 popen 相关的系统调用,在调用 popen 之前睡了 2s。通过如下截图可以看到,popen 的时候使用了管道,也通过 vfork 创建了子进程。

这篇关于system 和 exec 的区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1046313

相关文章

2.1/5.1和7.1声道系统有什么区别? 音频声道的专业知识科普

《2.1/5.1和7.1声道系统有什么区别?音频声道的专业知识科普》当设置环绕声系统时,会遇到2.1、5.1、7.1、7.1.2、9.1等数字,当一遍又一遍地看到它们时,可能想知道它们是什... 想要把智能电视自带的音响升级成专业级的家庭影院系统吗?那么你将面临一个重要的选择——使用 2.1、5.1 还是

Python中@classmethod和@staticmethod的区别

《Python中@classmethod和@staticmethod的区别》本文主要介绍了Python中@classmethod和@staticmethod的区别,文中通过示例代码介绍的非常详细,对大... 目录1.@classmethod2.@staticmethod3.例子1.@classmethod

Golan中 new() 、 make() 和简短声明符的区别和使用

《Golan中new()、make()和简短声明符的区别和使用》Go语言中的new()、make()和简短声明符的区别和使用,new()用于分配内存并返回指针,make()用于初始化切片、映射... 详细介绍golang的new() 、 make() 和简短声明符的区别和使用。文章目录 `new()`

Python中json文件和jsonl文件的区别小结

《Python中json文件和jsonl文件的区别小结》本文主要介绍了JSON和JSONL两种文件格式的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下... 众所周知,jsON 文件是使用php JSON(JavaScripythonpt Object No

结构体和联合体的区别及说明

《结构体和联合体的区别及说明》文章主要介绍了C语言中的结构体和联合体,结构体是一种自定义的复合数据类型,可以包含多个成员,每个成员可以是不同的数据类型,联合体是一种特殊的数据结构,可以在内存中共享同一... 目录结构体和联合体的区别1. 结构体(Struct)2. 联合体(Union)3. 联合体与结构体的

什么是 Ubuntu LTS?Ubuntu LTS和普通版本区别对比

《什么是UbuntuLTS?UbuntuLTS和普通版本区别对比》UbuntuLTS是Ubuntu操作系统的一个特殊版本,旨在提供更长时间的支持和稳定性,与常规的Ubuntu版本相比,LTS版... 如果你正打算安装 Ubuntu 系统,可能会被「LTS 版本」和「普通版本」给搞得一头雾水吧?尤其是对于刚入

python中json.dumps和json.dump区别

《python中json.dumps和json.dump区别》json.dumps将Python对象序列化为JSON字符串,json.dump直接将Python对象序列化写入文件,本文就来介绍一下两个... 目录1、json.dumps和json.dump的区别2、使用 json.dumps() 然后写入文

native和static native区别

本文基于Hello JNI  如有疑惑,请看之前几篇文章。 native 与 static native java中 public native String helloJni();public native static String helloJniStatic();1212 JNI中 JNIEXPORT jstring JNICALL Java_com_test_g

Android fill_parent、match_parent、wrap_content三者的作用及区别

这三个属性都是用来适应视图的水平或者垂直大小,以视图的内容或尺寸为基础的布局,比精确的指定视图的范围更加方便。 1、fill_parent 设置一个视图的布局为fill_parent将强制性的使视图扩展至它父元素的大小 2、match_parent 和fill_parent一样,从字面上的意思match_parent更贴切一些,于是从2.2开始,两个属性都可以使用,但2.3版本以后的建议使

Collection List Set Map的区别和联系

Collection List Set Map的区别和联系 这些都代表了Java中的集合,这里主要从其元素是否有序,是否可重复来进行区别记忆,以便恰当地使用,当然还存在同步方面的差异,见上一篇相关文章。 有序否 允许元素重复否 Collection 否 是 List 是 是 Set AbstractSet 否