system函数的分析

rt-thread源码分析篇八:rt_system_heap_init函数分析 一、前言 rt_system_heap_init被rt_hw_board_init调用。 rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); 二、参数分析 #define STM32_SRAM_SIZE 64 #define STM32_SRAM_END (0x20000000 + STM32_SRAM_SIZE * 1024) extern int Image$$RW_IRAM1$$ZI$$Limit; #define HEAP_BEG 阅读详情

该博文如果能对您有所帮助,不胜荣幸.由于本文完全是本人的理解,如果有错误,或者有其他的建议,请私信我,我会及时的回复或修改.

1. 首先我们来看一下,实现system函数的一些要求:
*a.在执行system的时候,应该屏蔽父进程的SIGINT,SIGQUIT信号*
为什么要这么做呢?
原因:用白话来讲,就是让system函数在执行的时候,获取子进程状态的不受干扰.如果有兴趣的话,可以看一下APUE那本书上的解释,我这里不在赘述.
*b.在实现system函数的时候,应该屏蔽SIGCHLD信号,在最后再解开*
那么为什么呢?
第一点原因:出在waitpid/wait函数上,(先声明一点,waitpid/wait的返回与SIGCLHD信号没有必然的关系)如果在调用system函数的外面注册了关于SIGCHLD的信号处理函数,waitpid/wait函数会等到信号处理函数结束之后,才会返回,所以如果信号处理函数执行的时间过长,那么对system这个函数是不利的.
第二个原因:
如果在外面有信号处理函数要捕捉SIGCHLD信号的话,我们在先前如果没有屏蔽SIGCHLD信号的话,在信号处理函数里面调用了waitpid()/wait()函数的话(很多种情况下都会这么做),那么在信号处理函数里面就将子进程的资源释放了,在system内部的waitpid()就因为获得不到子进程的状态信息,从而返回-1;
如果你有为什么在system内部有waitpid()函数的调用的疑问的话,我的解释是这样的,如果在外面没有调用waitpid怎么办?

下面我们来看一下,system实现的具体代码(有处理信号的方式)

int mysystem(const char* command)
{
    pid_t pid;
    int status;
    struct sigaction ignore,saveintr,savequit;
    sigset_t childmask,savemask;
    if(str == NULL)
    {
        return 1;
    }
    //首先不能让主进程接收到SIGINT,SIGQUIT信号
    ignore.sa_handler = SIG_IGN;
    sigemptyset(&ignore.sa_mask);
    ignore.sa_flags = 0;
    if(sigaction(SIGINT,&ignore,&saveintr)<0)
    {
        return -1;
    }
    if(sigaction(SIGQUIT,&ignore,&savequit)<0)
    {
        return -1;
    }
    sigemptyset(&childmask);
    sigaddset(&childmask,SIGCHLD);
    if(sigprocmask(SIG_BLOCK,&childmask,&savemask)<0)
    {
        return -1;
    }
    print_signal("begin:");
    pid = fork();
    if(pid < 0)
    {
        return -1;
    }
    if(pid == 0)
    {//在子进程中恢复SIGINT,SIGQUIT的先前状态
        sigaction(SIGINT,&saveintr,NULL);
        sigaction(SIGQUIT,&savequit,NULL);
        sigprocmask(SIG_SETMASK,&savemask,NULL);
        execl("/bin/sh","sh","-c",command,NULL);
        _exit(127); //是为了防止execl出错的时候用的,如果execl成功则不会执行这条语句
    }
    else
    {
        while(waitpid(pid,&status,0)<0)  //waitpid与SIGCHLD没有必然的关系
        {
            if(errno != EINTR)
            {
                status = -1;
                break;
            }
        }
        }
    }
    //恢复各种信号到调用system之前的状态
    if(sigaction(SIGINT,&saveintr,NULL)<0)
    {
        return -1;
    }
    if(sigaction(SIGQUIT,&savequit,NULL)<0)
    {
        return -1;
    }
    if(sigprocmask(SIG_SETMASK,&savemask,NULL)<0)
    {
        return -1;
    }//在这里执行完之后,才会执行信号处理函数(如果有的话)
    return status;
}

以上是system函数的具体实现。
那么我们下面就来讨论一下实现的一些细节,
a.为什么在父进程中要判断errno与EINTR之间的关系?
首先,我先说明一下,EINTR错误是怎么产生的:在WNOHANG(不阻塞,用于waitpid())没有被设置(也就是说waitpid()是在堵塞的情况下),一个不阻塞的信号或者是SIGCHLD信号,被捕捉了,那么waitpid将errno置成EINTR
其次,我们将errrno与EINTR相比的原因是:在实现system的过程中,我们要避免在子进程结束后,由于其他信号被捕捉而引起返回的waitpid的这种效果(前面也提过waitpid的返回与SIGCHLD没有必然的关系),这里的waitpid意义,我觉得是在等待子进程的结束,如果是因为这里的waitpid将错误原因为ENITR的时候,我们需要重试waitpid,因为我们在前面已经屏蔽了SIGCHLD信号,所以这里不可能是捕捉到的是SIGCHLD信号。如果不是EINTR,那就说明是真的出问题了,我们将status改编成-1,这也对应了我们system的返回值需要(在下面会有讲到)。

system这个函数在command有效的时候,有三种情况的返回值
1.如果fork,waitpid函数出错(除了EINTR)以外,都回返回-1
第一种情况最容易理解,因为我们在实现的时候,就是这么写的嘛,没有什么可说的。

2.如果是execl的问题的话,那么就会返回127
第二种情况的话,就是如果execl不成功,那么肯定会继续向下执行,然后执行了_exit(127)这条语句,自然就会返回127

3.否则其他时候,返回的都是shell脚本的状态值(status值)
首先,我们应该理解一点的就是,由于fork出来的子进程,在其执行的时候,就被execl替换了,那么子进程的执行路线,也就自然而然的走向execl所指定的道路,也就是说execl语句后面的语句,子进程不会再执行了.
至于为什么会这样呢?
我是这样认为的,exec函数族的作用就是用于替换进程的用户空间的,在执行execl的路线的时候,因为在每个可执行的二进制程序生成的时候,我们的编译器都回在代码末尾添加exit(0),用来冲洗缓冲区,关闭一些资源用的.所以在执行完execl之后,就肯定会执行到exit(0)这条语句,那么该子进程就会结束.从而就不会执行下面的语句了,在换句话来说,就是不会再返回原程序中了.所以我们在使用waitpid()获得status的时候,获得的是execl函数替换的shell脚本的返回值(状态);

参考链接:
http://blog.youkuaiyun.com/astrotycoon/article/details/40626355
http://blog.chinaunix.net/uid-24774106-id-3048281.html?page=3

使用system函数执行命令的详细分析及编程示例 当程序调用system函数时,它会创建一个新的子进程,并在子进程中调用shell来执行指定的命令。在这个示例中,我们使用system函数执行了一个"ls -l"命令,即列出当前目录下的文件和文件夹的详细信息。system函数是C语言标准库提供的一个函数,它可以在程序中执行一个shell命令,并等待命令执行完成后再继续程序的执行。在实际编程中,我们应该谨慎使用system函数,确保传入的命令字符串的来源可靠,并进行必要的安全检查。函数返回值表示命令的执行结果,如果命令执行成功,则返回一个非零值,否则返回0。 阅读详情

相关推荐

用Coze平台30分钟打造《花光10亿》小游戏:零代码AI开发实战

本文详细介绍了如何利用字节跳动推出的Coze平台,在30分钟内零代码开发一款名为《花光10亿》的AI小游戏。通过配置提示词、集成图像生成插件、构建自动化工作流以及使用数据库功能,即使没有编程基础的用户也能快速将创意转化为可交互的智能应用,体验AI开发的便捷与高效。

weixin_29313547的博客 208

C语言的system()函数详解

函数原型 包含在头文件 “stdlib.h” 中 int system(const char * command) 函数功能 执行 dos(windows系统) 或 shell(Linux/Unix系统) 命令,参数字符串command为命令名。另,在windows系统下参数字符串不区分大小写。 说明:在windows系统中,system函数直接在控制台调用一个command命令。 在Linux...

dark_cy的博客 19万+

STM32巡线小车PID调参实战:从五路灰度传感器数据到稳定运行的避坑指南

本文详细介绍了STM32巡线小车的PID调参实战,从五路灰度传感器数据处理到PID参数优化,提供了系统化的调试方法和常见问题解决方案。通过加权平均法计算偏移量,逐步调整比例、积分、微分参数,实现小车稳定巡线。文章还涵盖了定时器配置、控制周期优化及高级调试技巧,帮助开发者避开常见陷阱,提升巡线性能。

weixin_42570484的博客 194

详解C语言system()函数,一个函数让初学者的代码有趣(一)

首先使用system函数要包含头文件#include ,system函数可以通过调用一些命令来实现一些特殊的功能,我们这里直接就开始讲解了,主要是为了让大家可以先快速上手,之后会出一篇更详细的讲解。

freed_Day的博客 1万+

AI智能体安全沙箱agentguard:为LLM代码执行筑起防火墙

在AI应用开发领域,大语言模型(LLM)驱动的智能体(Agent)能够自动生成并执行代码,极大地提升了自动化能力。然而,赋予AI直接执行系统命令的权限也带来了显著的安全风险,如恶意代码注入、敏感数据泄露和系统资源滥用。为了解决这一核心矛盾,安全沙箱技术应运而生,它通过在不可信代码与宿主系统之间建立隔离层,实现"默认拒绝、最小权限"的安全原则。agentguard项目正是这一理念的工程实践,它结合白名单机制与容器化隔离,为AI智能体提供了可配置、可审计的安全执行环境。该方案不仅适用于内部自动化工具开发,也为构

weixin_28695537的博客 297

VIO实战前传:手把手教你解读Kalibr双目IMU标定报告与参数应用

本文详细解析Kalibr双目IMU联合标定报告的核心参数与应用方法,涵盖重投影误差分析、IMU误差指标解读、关键变换矩阵原理及VINS-Fusion实战配置。通过手把手教学帮助开发者准确理解标定结果,解决VIO算法落地中的参数配置难题,提升视觉惯性里程计的系统稳定性与精度。

weixin_42699679的博客 334

全网最全c++中的system详解

1,简介system()函数是在C++制作中十分常用,有用的一个函数。其效果类似于系统中"cmd"控制台和"bat"文件。通常会在C++字符游戏,和C++整蛊程序中使用。其形式是以:system("***");呈现。

HenryC0509的博客 2万+

傅里叶光学(1)

傅里叶光学,可以看作是通信理论中傅里叶变换等一系列数学思想以及系统理论与光学(主要是衍射光学)相结合的产物关于傅里叶光学的应用领域,本节介绍了成像,当然事实上不可能仅限于成像,经典的还如激光散斑的一些应用,干涉计量,还有傅里叶变换光谱学等等。最后总结一下,傅里叶光学我认为可以看做一个工具,对于任意的系统,它能给出一些数学思想与物理原理进行解释和分析,找出系统的扰动和响应的关系,或者说根据扰动和响应,来研究或者设计一个系统。

m0_53607446的博客 1684

system()函数详解及用法

System()用于调用一些DOS命令,执行dos(windows系统) 或 shell(Linux/Unix系统) 命令,参数字符串command为命令名。在windows系统,system函数直接在控制台调用一个command命令;在Linux/Unix系统中,system函数会调用fork函数产生子进程,由子进程来执行command命令,命令执行完后随即返回原调用的进程。system的原型函数为:int system(const char * command)

JDSNYD的博客 5004

ubuntu下安装多版本cuda及版本切换教程

首先,从官网下载所需版本的cuda安装包,下载链接。选择对应版本后,会跳转到该版本的配置信息页面。比如我是ubuntu20.04系统,已经安装好了cuda10.0,但是现在还需要用到cuda9.0。那么,在选定版本后,配置信息如下图所示(由于Version选项中没有20.04,因此我们随便选一个即可,这里选的16.04,这一选项不会影响后面的安装),Installer Type选择为runfile(因为使用deb文件进行安装的话,可能会将已经安装的较新的显卡驱动给替换掉),选择好之后点击Base Insta

zeeq的博客 3万+

CDD那些事 - DID and SecurityAccess

本文介绍了SecurityAccessSID27的安全访问配置流程:1.通过StateGroups添加Level2群组;2.在Classes定义L2子功能;3.配置4步解锁流程,选择对应解锁等级;4.在DiagnosticInstance设置请求响应。同时说明了DID配置的两种方式:在DIDs页面定义或通过Identification页面创建,前者定义更全面。文章还提到ServiceList支持view/edit模式,其中edit模式可配置DID的多服务支持(如同时支持SID22读取和SID2E写入),但该

ziteng21的博客 256

Linux下system () 函数详解简介,system()与execl()的区别,popen()

Linux下system () 函数详解简介,system()与exec()的区别

ken2232的博客 8495

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

system函数的分析以及总结

信号

沧海一声笑的专栏 1198

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

system函数分析

Linux中的system函数详细分析 相关函数  fork,execve,waitpid,popen  表头文件  #include  定义函数  int system(const char * string);  函数说明  system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命>令执行完后随即

jk110333的专栏 1090

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

system函数返回值测试分析

man system可以看到如下返回值说明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        status  is in the for

失语者的专栏 1602

Linux中的system函数详细分析

Linux中的system函数详细分析<br />[size=2]system()函数功能强大,很多人用却对它的原理知之甚少,也就有了上面那么多的回帖,我想大家如果知道了system的具体实现就不会对楼主程序在很多编译器中不能表现自己希望的功能感到费解了。我对linux中的实现比较了解,具体分析这个,windows中的类似就不详解了。<br /><br />好了,先看linux版system函数的源码:[code]#include <br />#include <br />#include <br />#i

gogor的专栏 1235

Linux下system类似函数,linux下system函数的简单分析

简单分析了linux下system函数的相关内容,具体内容如下int__libc_system (const char *line){ if (line == NULL) /* Check that we have a command processor available. It might not be available after a chroot(), for example. ...

weixin_28727975的博客 491

linux下system函数头文件,linux下system函数的简单分析

1 int2 __libc_system (const char *line)3 {4 if (line ==NULL)5 /*Check that we have a command processor available. It might6 not be available after a chroot(), for example.*/7 return do_syst...

weixin_34258386的博客 2030

系统调用入口函数源码分析system_call——X86_64

在实验中用到这一块,就去看源码分析整理了一下,全部为个人理解。有错误的地方,希望和大牛交流。 首先解释一下,我实验的目的是获得系统调用入口函数system_entry的起始地址和函数大小。 在linux-3.10.1, x86 64位的系统下,系统调用的入口地址保存在MSR寄存器中,通过rdmsrl(MSR_LSTAR,ksystem_call);便可获得系统调用的入口地址,然后对该入口地址进

zdd_11111的博客 8358

linux下system函数的简单分析

1 int 2 __libc_system (const char *line) 3 { 4 if (line == NULL) 5 /* Check that we have a command processor available. It might 6 not be available after a chroot(), fo...

weixin_30838921的博客 114

APUE——system函数详细分析

相关链接 信号屏蔽集的继承关系 fork后,子进程继承了父进程的信号屏蔽集,但是由于是两个存储空间,所以更改子进程的信号屏蔽集,并不改变父进程的信号屏蔽集 #include "apue.h" struct sigaction act; sigset_t old; void fun(); //void funchild(); pid_t pid; void pr_mask(const char *...

weixin_44537992的博客 826

linux system函数分析

system函数是在应用编程里面想调用外部命令时最方便的方式了,除非想要获取命令行执行的输出信息, 那system就不行了,需要用popen。但是system内部具体怎么实现及怎么处理它的返回值经常被忽略,我认为还是得特别注意。 关于system的实现用manpage里面的话: DESCRIPTION The system() library function uses fork(2...

weixin_30633507的博客 190

Dalvik模式下System.loadLibrary函数的执行流程分析

本文博客地址:http://blog.youkuaiyun.com/qq1084283172/article/details/78212010 Android逆向分析的过程中免不了碰到Android so被加固的情况,要对被加固的Android so进行脱壳处理,就需要先了解Android so的加载流程,进而了解A...

墨鱼菜鸡 311
上一篇: 自旋锁
下一篇: 线程同步
莫浮沉心
博客等级 码龄11年 4粉丝 5原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值