system函数和fork-exec机制

C语言的多进程fork()、函数exec*()、system()与popen()函数 阅读详情

system函数

使用man system查看帮助如下:

NAME
       system -execute a shell command
 
SYNOPSIS
       #include<stdlib.h>
 
       intsystem(const char *command);
 
DESCRIPTION
       system()  executes a command specified in command by calling
       /bin/sh -ccommand, and returns after the command  has  been
      completed.   During execution ofthe command, SIGCHLD will be
       blocked, andSIGINT and SIGQUIT will be ignored.
 
RETURN VALUE
       The value returned is -1 on error (e.g.  fork(2) failed), and
       the  return status  of  the command otherwise.  This latter
       return statusis in the format specified in wait(2).   Thus,
       the exit code of thecommand will be WEXITSTATUS(status). In
       case /bin/shcould not be executed, the exit status will  be
       that of acommand that does exit(127).
 
       If the valueof command is NULL, system() returns non-zero if
       the shell isavailable, and zero if not.
 
       system() doesnot affect the wait status of any other  chil-
       dren.

说明:

以/bin/sh -c command的方式执行命令,如果命令之间用“; ”隔开,则可以执行多条指令。

system是一个同步函数,即执行完之后才会返回,内部实现也类似与fork-exec机制(执行期间会阻塞SIGCHLD信号,同时忽略SIGINT、SIGQUIT)。

如何判断system是否执行成功:

1、   fork成功:-1 != status

2、   system命令是否正常终止:WIFEXITED(status)非0 ,非正常终止=0

3、   根据返回值判断:WEXITSTATUS(status)== 0  //获取system的返回值(低八位,可以理解为unsignedbyte);如果shell命令无法执行,则返回127,命令检测到有错误,则返回1-126

注意:

当shell脚本不存在、没有执行权限等场景下时,以上前2个条件仍会成立,此时WEXITSTATUS(status)为127,126等数值。

所以,我们在shell脚本中不能将127,126等数值定义为返回值,否则无法区分中是shell的返回值,还是调用shell脚本异常的原因值。shell脚本中的返回值最好多1开始递增。

fork-exec机制

此机制用于执行一个新的进程。System函数的内部实现采用的也是fork-exec机制,下面是fork-exec的一个示例:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
 
int main(int argc, char *argv[])
{
         pid_t pid =0;
         pid =  fork();
         if (pid <0)
         {
                  printf("forkerror!\n");
                  exit(-1);
         }
         else if (0 ==pid)
         {
                  //childprocess
                  char* const szArgs[] = {"sleep", "10", NULL};
// bookmark:1
                  if(-1== execvp("/bin/sleep", szArgs))
                  {
                            printf("execvperror!\n");
                            _exit(-1);
                  }
         }
         else
         {
                  //parentprocess
                  charszCmd[64]={0};
                  snprintf(szCmd,sizeof(szCmd), "kill -9 %d", pid);
// bookmark:2
                  //system(szCmd);    //to cause unormal terminate, you canannotate it  
                  intstatus= 0;
                 
                  pid= wait(&status);
                  if(WIFEXITED(status)) // normal terminate
                  {
                            if(0 == WEXITSTATUS(status))
                            {
                                     printf("processexecute success, exit code=%d", status);
                            }
                            else
                            {
                                     printf("processexecute failed, exit code = %d, WEXITSTATUS(status) = %d",status,WEXITSTATUS(status));
                            }
                  }
                  else
                  {
                            printf("processterminated unormally, pid = %d, status = %d, WEXITSTATUS(status) = %d\n",pid, status, WEXITSTATUS(status));
                  }
         }
         return 0;
}

运行看看,一探究竟:

1)       当把bookmark:1下面的 sleep改为ssleep时(即命令不正确),输出结果为

execvp error!

process execute failed, exit code = 64256, WEXITSTATUS(status)= 255

表明execvp返回-1,捕获的WEXITSTATUS(status)=255(-1), 但这种情况算正常终止,WIFEXITED(status) 非0.

2)       当把 bookmark:2 下面的system语句注释掉,输出结果为:

process terminated unormally, pid = 17584, status = 9,WEXITSTATUS(status) = 0

表明程序非正常终止,WIFEXITED(status) == 0.

总结:

从程序运行的结果看,可以得出几条结论:当exec shell命令不存在或没有执行权限时,execvp执行的进程仍算正常终止,而当execvp运行期间被终止时,算异常终止。

说明:

子进程的结束状态返回后存于status,底下有几个宏(位于头文件sys/wait.h)可判别结束情况:
WIFEXITED(status)如果子进程正常结束则为非0值。
WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED来判断是否正常结束才能使用此宏。
WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真
WTERMSIG(status)取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。
WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。
WSTOPSIG(status)取得引发子进程暂停的信号代码,

参考链接:

http://blog.chinaunix.net/uid-10554711-id-2948333.html

http://blog.youkuaiyun.com/cheyo/article/details/6595955

电源管理芯片PMIC (Power Management Integrated Circuits,简称:将电源电压转换为电子设备各部分所需的适当电压水平,包括升压(Boost)、降压(Buck)和升降压(Buck-Boost)转换。:控制和限制流向电子设备各部分的电流,以保护组件免受过电流损害。:管理多个电源轨,为不同的部分提供稳定的电能控制。电源轨指电路板上传输电力的线路。电源监控:提供过电压、欠电压、过电流、过热和短路保护,以防止电子设备损坏。:通过高效的电源转换技术,减少能量损耗,提高能源利用效率。 阅读详情

相关推荐

HDMI2.1接口保护指南:从浪涌损坏案例看RK3588板子的ESD设计要点

本文深入探讨了HDMI2.1接口在RK3588板子上的ESD防护设计要点,通过真实案例分析了浪涌损坏的原因及解决方案。重点介绍了TMDS信号链路的四级防护体系、TVS管选型误区以及连接器与PCB的协同设计策略,帮助工程师有效避免静电放电导致的HDMI无输出故障。

weixin_29305337的博客 446

【2022-12-16】使用 fork-exec模型编写守护进程一个注意点

在编写 fork-exec模型的守护进程时,在while循环中,使用fork创建子进程,在pid=0的条件下,使用execvp函数替换当前程序;

程序员沙子的专栏 283

舵机PWM信号转互斥继电器开关信号

-----------------本文由“麦粒电子”撰写,并提供相应产品服务。---------------- 叙述 上次的PWM转继电器开关方案得到大家的不少好评(博客链接),但是发现有些玩家需要一路PWM同时去控制两路继电器开关通断,并且两者是互斥的,好去控制两种不同的负载。所以就继续升级了如下的模块。 正常的控制部件顺序这样:遥控器按钮拨动,遥控器接收机相应通道PWM值变化,PWM转开关模块检测PWM值发生变化从而驱动相应机械继电器触点吸合释放。本模块的两个继电器动作是互斥的,也就是不会同时吸合。

Mai_LiElectronic的博客 1627

sys.fork_exec和os.excute实现的差异

函数sys.fork_exec和os.excute实现的差异 os.excute是lua os库中实现的函数 /lua/src/src/loslib.c static const luaL_Reg syslib[] = { 236 {“clock”, os_clock}, 237 {“date”, os_date}, 238 {“difftime”, os_diff...

vickytong1018的博客 1860

怎么定位K8s容器中运行的JAVA程序OOM异常(一)

一.前置环境 1. 运行在k8s集群上的Pod服务(Java程序) 2. MAT分析工具 二.利用Jmap工具导出Heap Dump 1.执行命令进入pod容器 kubectl exec -itn {namespace} {pod}} sh 2.利用jmap生成java程序的Dump文件 jps | grep {jar} ./jmap -dump:live,format=b,file=haep.hprof 8 3.利用k8s命令导出Dump文件到本地 kubectl cp -n

计算科学 3013

在Docker中集成GPU监控体系

先上效果图 等文档整理出来再更

tamako0v0的博客 2470

Linux -- system函数学习记录

Linux C编程中,调用另一个可执行文件或调用命令可以使用system函数和exec系列的函数。 下面关于system函数的一些方法和使用做一个简单的记录。 system在程序中执行一个命令字符串很方便,在man system的时候,可以看到 #include <stdlib.h> int system(const char *command); system()通过调用/...

青椒*^_^*凤爪爪的博客 4384

[Python图像识别] 五十二.水书图像识别 (2)基于机器学习的濒危水书古文字识别研究

上一篇文章详细讲解如何利用数据增强方法实现图像数据集的扩充,并以濒危水书作为案例讲解。这篇文章将详细讲解基于机器学习的水书图像识别方法,以图像像素统计为特征开展图像分类讲解,这是最基础的方法,也为后续深度学习图像分类描述提供支撑。基础性文章,希望对您有所帮助!让我们开始吧,且看且珍惜。

杨秀璋的专栏 989

ucore lab5用户进程管理 实验报告

实验目的 了解第一个用户进程创建过程 了解系统调用框架的实现机制 了解ucore如何实现系统调用sys_fork/sys_exec/sys_exit/sys_wait来进行进程管理 实验内容 实验4完成了内核线程,但到目前为止,所有的运行都在内核态执行。实验5将创建用户进程,让用户进程在用户态执行,且在需要ucore支持时,可通过系统调用来让ucore提供服务。为此需要构造出第一个用户进程,并通过系统调用sys_fork/sys_exec/sys_exit/sys_wait来支持运行不同的应用程序,完成

jzb的博客 1057

书旗app字符串加密分析

本文案例是对书旗app搜索接口的请求密文进行分析和逆向。

李玺 3155

YTM32B1M SDK解析31:软件I2C驱动详解

YTM32B1M微控制器软件I2C驱动解析 本文详细介绍了YTM32B1M微控制器中通过GPIO引脚模拟I2C总线的软件实现方案。核心内容包括: 驱动架构:采用swi2c_config_t配置结构体和swi2c_state_t状态结构体管理I2C参数 功能接口:提供初始化、数据传输(主/从模式)、底层控制等API 应用示例:包含基本配置、EEPROM读写、传感器数据采集、总线扫描等典型应用场景 优化建议:给出引脚选择、时序配置、错误处理等方面的最佳实践 该驱动在硬件I2C资源不足时提供可靠替代方案,支持标准

VehSwHwDeveloper的博客 158

linux 的exec函数,Linux 软件系列之九——exec函数族和system函数调用

1.exec函数族可以实现在一个进程中启动另一个程序的功能。系统内核会使用新的程序替换原有进程中使用的程序。开始新程序的执行。新进程和原有的进程号相同。调用exec函数后,代码段中的内容被新进程的代码替换,接着更新堆栈段和数据段。2.exec函数族说明:为什么一直说exec函数族呢?因为,在Linux中,并不存在exec这个函数,而是一组以exec开头的函数。这6个函数的功能是相同的,我们常用的是...

weixin_39635314的博客 411

AIGC 算法工程师面试八股文全解析:Diffusion Models 原理、推导与实战要点

特性 | 重参数化技巧 (Reparameterization Trick) |本质| 将随机变量的采样过程从不可导的随机操作转换为可导的确定性函数与一个已知分布的随机噪声的组合。目的。

m0_71589036的博客 402

system函数与exec函数族

/ 示例:执行程序并传递新环境变量。

陈小陈的博客 895

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

进程创建system、exec、fork

通过system库函数创建进程system的原型如下, 其作用是运行以字符串参数的形式传递给它的命令并等待该命令的完成。其作用等价于在shell中执行命令sh -c string。#include <stdlib.h>int system(const char *string);#include <stdlib.h> #include <stdio.h>int main() { printf

aitumingmumu的专栏 921

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

system/exec/fork/pthread基本概念

1.system函数 函数头文件: #include 函数定义: int system(const char * string);  函数说明: System()会调用fork()产生子进程,由子进程调用string字符串所代表的命令,此命令执行完后随机返回调用进程。 返回值 -1 出现错误 0 调用成功但是没有出现子进程 >0 成功退出的子进程ID 在system函数里,会

springwinter008的专栏 857

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

别再死记硬背了!图解Linux中system、exec和fork/wait的区别与选用场景

本文深入解析Linux中system、exec和fork/wait三种进程控制方法的本质差异与适用场景,通过可视化对比和实战案例,帮助开发者建立清晰的决策框架。文章详细介绍了system()的简易性、exec函数族的进程替换特性以及fork()/wait()的精细控制能力,并提供了性能对比表和场景化选择指南,助力开发者高效进行Linux进程管理。

weixin_30458043的博客 599

Linux 进程控制核心:exec 族函数、waitpid 与 system 全解析

exec 族:程序替换核心,fork+exec 是 Linux 进程编程的经典组合,exec 成功则进程被替换,失败才返回;waitpid:子进程资源回收的唯一方式,阻塞 / 非阻塞模式适配不同场景,避免僵尸进程;system:便捷但受限,无法修改父进程状态,底层是 fork+exec+waitpid;路径控制:getcwd 获取当前路径,chdir 修改路径(仅影响当前进程);核心原则。

2301_77424087的博客 1051

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 = fo

weixin_53762042的博客 1744

深入解析进程管理:wait、exec与system函数原理与实践

在操作系统与软件开发领域,进程管理是核心基础概念之一,它涉及程序从创建到执行再到终止的完整生命周期。其基本原理是通过系统调用实现进程的创建、执行和状态同步,这一机制为现代软件提供了并发执行和资源隔离的技术基础。从技术价值看,掌握进程管理不仅能提升程序性能与稳定性,更是理解容器化、服务编排等高级架构的基石。在实际应用场景中,无论是开发需要调用外部工具的后台服务,还是构建任务调度系统,都离不开对进程创建、程序替换和状态回收等操作的精准控制。本文聚焦于进程管理的三个关键函数:wait用于进程资源回收与状态同步,能

cuankuangzhong6373的博客 581

fork与vfork、exec与system

比较fork与vfork之间的区别:都为创建一个子进程, 1、前者是将父进程的内存数据copy到子进程中,而后者则是共用父进程的内存数据 2、vfork:创建过子进程之后,阻塞父进程,当子进程调用exit()或者exec()后父进程开始往下运行。。 注:vfork返回只能调用exit而不能使用return,,因为子进程与父进程共享一片内存,子进程return之后,释放局部变量、弹

我不会编程,但不是完全不会,我会一点点 789

linux 进程fork wait exec

1、创建子进程 fork() 和 vfork() fork() #include <unistd.h> pid_t fork(void); //失败返回-1;成功:父进程返回子进程的ID(非负) 子进程返回 0 //pid_t 类型表示进程 ID,但为了表示-1,它是有符号整型。(0 不是有效进程 ID,init 最小,为 1) #include <stdio.h&g...

damonlearning的博客 583

关于glibc的system函数调用实现

system在glibc下的实现

Blue summer的博客 1583

父子进程(fork、exec函数)

当一个子进程被创建时(例如通过fork()系统调用),。这是进程属性继承的一部分,属于 POSIX 标准行为。:子进程会复制父进程的当前工作目录路径(通过getcwd()获取的值)。:子进程后续对工作目录的修改(如chdir(),反之亦然。:工作目录路径字符串本身属于进程内存数据,遵循写时复制机制(实际修改时才分离)。。子进程仅继承创建时刻的快照,后续双方独立修改。A:在子进程中主动调用chdir(),或使用exec()系列函数时通过参数指定(如fexecve()的dirfd。

m0_68381723的博客 815

别再死记硬背了!图解Linux进程创建:fork、vfork、exec和system到底怎么选?

本文深入解析Linux进程创建函数fork、vfork、exec和system的核心机制与适用场景,帮助开发者理解写时复制(COW)等底层原理,掌握进程管理的最佳实践。通过对比分析各函数的行为特征、性能差异和安全风险,提供实战选择指南,解决Linux系统编程中的进程创建难题。

weixin_33736048的博客 543

system和popen的用法

1.system #include &amp;lt;stdlib.h&amp;gt; int system(const char *command); system() executes a command specified in command by calling /bin/sh -c command, and returns after the command has been completed. ...

willinux的专栏 1545
上一篇: 常用的一些加密算法
下一篇: stl容器中的元素删除方法
LinuxG_G
博客等级 码龄15年 58粉丝 176原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值