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 创建了子进程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/696343.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pdf的压缩该怎么做?快速在线压缩pdf的方法

pdf文件是现在很常用的一种文件格式&#xff0c;有很多的文件内容都可以通过这种格式来展示内容&#xff0c;比如一些通知文件、设计图、个人信息等等&#xff0c;文件的内容越多就会越大&#xff0c;在使用的时候经常会受到一定的限制。那么有什么方法能够快速的将pdf文件变小…

计算机提示msvcp120.dll如何修复,7个不同方法分享

msvcp120.dll 是 Microsoft Visual C Redistributable 的一个关键组件&#xff0c;它包含了 C 运行时库&#xff0c;这些库对基于 Visual C 编写的应用程序至关重要。当应用程序运行时&#xff0c;msvcp120.dll 会被加载到内存中以提供必要的函数和类支持。 一、msvcp120.dll功…

详解python中的pandas.read_csv()函数

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主。 &#x1f913; 同时欢迎大家关注其他专栏&#xff0c;我将分享Web前后端开发、人工智能、机器学习、深…

从GPU到ASIC,博通和Marvell成赢家

ASIC市场上&#xff0c;博通预计今年AI收入将达到110亿美元以上&#xff0c;主要来自与Google和Meta的合作&#xff1b;Marvell预计2028年AI收入将达到70亿至80亿美元&#xff0c;主要来自与Amazon和Google的合作。 随着芯片设计和系统复杂性的增加&#xff0c;科技大厂将更多地…

初阶 《函数》 2.C语言中函数的分类

2.C语言中函数的分类 1.库函数 2.自定义函数 2.1 库函数 为什么会有库函数&#xff1f; 1.我们知道在我们学习C语言编程的时候&#xff0c;总是在一个代码编写完成之后迫不及待的想知道结果&#xff0c;想把这个结果打印到我们的屏幕上看看。这个时候我们会频繁的使用一个功能…

排序-快排算法对数组进行排序

目录 一、问题描述 二、解题思路 1.初始化 2.将右侧小于基准元素移到左边 3.将左侧大于基准元素移到右边 4.重复执行上面的操作 5.对分好的左、右分区再次执行分区操作 6.最终排序结果 三、代码实现 四、刷题链接 一、问题描述 二、解题思路 快排算法实现数组排序&am…

配置 JDK 和 Android SDK

目录 一、配置JDK 1. 安装 JDK 2. JDK 环境配置 3. JDK的配置验证 二、配置 adb 和Android SDK环境 1、下载 2、配置 Android SDK 环境 一、配置JDK 1. 安装 JDK 安装链接&#xff1a;Java Downloads | Oracle 我安装的是 .zip &#xff0c;直接在指定的文件夹下解压就…

产品创新:驱动企业增长的核心动力

在当今快速变化的市场环境中&#xff0c;产品创新已成为企业生存和发展的关键。产品创新不仅涉及全新产品或服务的开发&#xff0c;也包括对现有产品或服务的持续改进和优化。本文将深入探讨产品创新的定义、重要性以及如何通过创新驱动企业增长&#xff0c;并结合实际案例进行…

Redis系列之淘汰策略介绍

Redis系列之淘汰策略介绍 文章目录 为什么需要Redis淘汰策略&#xff1f;Redis淘汰策略分类Redis数据淘汰流程源码验证淘汰流程Redis中的LRU算法Redis中的LFU算法 为什么需要Redis淘汰策略&#xff1f; 由于Redis内存是有大小的&#xff0c;当内存快满的时候&#xff0c;又没有…

IO进程线程(十一)进程间通信 消息队列

文章目录 一、IPC(Inter-Process Communication)进程间通信相关命令 &#xff1a;&#xff08;一&#xff09;ipcs --- 查看IPC对象&#xff08;二&#xff09;获取IPC键值&#xff08;三&#xff09;删除IPC对象的命令&#xff08;四&#xff09;获取IPC键值的函数1. 函数定义…

13 RTP包的使用

RTP RTP包最主要的就是Sequence number。 对于发送者来说&#xff0c;视频的每一个帧都有很多包组成。对于接收端来接收的时候是有一个队列进行接收的。这个队列大小都是通过计算的。有了队列之后就会不断的往队列中插入数据。当队列中有的数据超时一直组不成包的时候&#xf…

k8s离线部署Calico网络(2续)

下载离线镜像 百度网盘 链接&#xff1a;https://pan.baidu.com/s/14ReJW-ZyYZFLbwSEBZK6mA?pwdi6ct 提取码&#xff1a;i6ct 1.将离线镜像上传至所有服务器并解压&#xff1a; [rootmaster ~]# tar xf calico.tar.gz [rootmaster ~]# cd calico 2.所有服务器使用for循环导入…

【微服务】springcloud-alibaba 配置多环境管理使用详解

目录 一、前言 二、配置多环境问题概述 2.1 什么是微服务多环境配置管理 2.1.1 微服务多环境配置管理问题起源 2.2 为什么要做多环境配置管理 2.3 微服务多环境配置管理解决方案 三、springboot 配置多环境管理解决方案 3.1 前置准备 3.1.1 搭建一个springboot工程 3.…

IO流(转换流)

InputStreamReader&#xff08;字符输入转换流 &#xff09; 解决不同编码时&#xff0c;字符流读取文本内容乱码的问题 public static void main(String[] args) {try (//1.得到文件的原始字节流(GBK的字节流形式)FileInputStream is new FileInputStream("src/666.tx…

前端实现点击图片放大查看,并点击关闭

效果展示 HTML 代码 HTML代码比较简单&#xff0c;包含了一个img元素&#xff0c;用显示原有图片&#xff0c;和一个模态框元素div&#xff0c;用于显示放大之后的图片元素&#xff0c;模拟模态框的样式 <!DOCTYPE html> <html lang"en"> <head>…

Vue3全局封装dialog弹框

Vue3全局封装modal弹框使用&#xff1a; 应用场景&#xff1a;全局动态form表单弹框 应用Vue3碎片&#xff1a; ref&#xff0c;reactive&#xff0c;app.component&#xff0c;defineExpose&#xff0c;defineProps&#xff0c;defineEmits 应用UI: element-plus dialog form …

MySQL系列-安装配置使用说明(MAC版本)

1、前言 本文将介绍MySQL的安装配置以及基本语法操作说明 环境&#xff1a;mac 版本&#xff1a;MySQL 8.0.28 之前电脑安装卸载过&#xff0c;后面在装的时候遇到一些问题&#xff0c;用了四五天才解决&#xff0c;主要是参考 https://blog.csdn.net/zz00008888/article/deta…

动态内存管理(malloc,calloc,realloc,free)+经典笔试题

动态内存管理 一. malloc 和 free1. malloc2. free 二. calloc三. realloc四.动态内存的错误1.对NULL指针的解引用操作2.对动态开辟空间的越界访问3.对非动态开辟内存使用free释放4.使用free释放一块动态开辟内存的一部分5.对同一块动态内存多次释放6.动态开辟内存忘记释放&…

streamlit:如何快速构建一个应用,不会前端也能写出好看的界面

通过本文你可以了解到&#xff1a; 如何安装streamlit&#xff0c;运行起来第一个demo熟悉streamlit的基本语法&#xff0c;常用的一些组件使用streamlit库构建应用 大模型学习参考&#xff1a; 大模型学习资料整理&#xff1a;如何从0到1学习大模型&#xff0c;搭建个人或企业…

SQL Chat:从SQL到SPEAKL的数据库操作新纪元

引言 SQL Chat是一款创新的、对话式的SQL客户端工具。 它采用自然语言处理技术&#xff0c;让你能够像与人交流一样&#xff0c;通过日常对话的形式对数据库执行查询、修改、创建及删除操作 极大地简化了数据库管理流程&#xff0c;提升了数据交互的直观性和效率。 在这个框…