Linux下system()函数的实现
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> #include <sys/types.h>
#include <sys/wait.h>
#include <signal.h> /* 参考 glibc sysdeps/posix/system.c: __libc_system/do_system */
int test_system(char* cmd)
{
int status;
pid_t pid;
struct sigaction sa;
struct sigaction intr, quit;
sigset_t omask; if (NULL == cmd) {/* glibc中当cmd为空时, 将cmd赋值为 'exit 0' */
return 0;
} sa.sa_handler = SIG_IGN; /* 对捕获的信号采取忽略操作 */
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask); /* 清空信号集, 不包含任何信号 */ /* 忽略 SIGINT 和 SIGQUIT 信号, 为什么?
有谁知道吗?
参考:https://www.cons.org/cracauer/sigint.html */
sigaction(SIGINT, &sa, &intr); /* 原有 SIGINT 处理存储到 intr 中, 用于恢复 */
sigaction(SIGQUIT, &sa, &quit); /* 原有 SIGQUIT 处理存储到 quit 中,用于恢复 */ /* 阻塞SIGCHLD信号,为什么?
子进程结束后,内核会给父进程发送SIGCHLD信号, 如果你注册了该信号的处理函数,并且
在其中也用waipid获取了子进程结束的状态, 当信号处理函数先于system中waitpid执行,
随后system函数中的waipid就会返回 No child processes 错误,无法获取到shell命令执行的结果, 只能返回 -1.
阻塞SIGCHLD可以确保system中waitpid先执行, 以获取子进程结束状态,
阻塞SIGCHLD期间, 如果还有其他子进程退出, 那么他们产生的SIGCHLD信号也会阻塞,
但是阻塞解除后你只会收到一个SIGCHLD通知,如果你需要使用waitpid获取所以子进程状态,那么需要循环调用waitpid */
sigaddset(&sa.sa_mask, SIGCHLD); /* 复用面前的信号集(空的), 将SIGCHLD信号加入信号集 */
sigprocmask(SIG_BLOCK, &sa.sa_mask, &omask); /* 阻塞信号集中的信号(其实信号集中只有SIGCHLD信号) */ pid = fork();
if (pid == (pid_t)0) {/* 子进程 */
const char *new_argv[4];
new_argv[0] = "sh";
new_argv[1] = "-c";
new_argv[2] = cmd;
new_argv[3] = NULL; /* 子进程继承父进程的信号掩码, 恢复SIGINT和SIGQUIT的信号处理操作. */
sigaction(SIGINT, &intr, (struct sigaction *)NULL);
sigaction(SIGQUIT, &quit, (struct sigaction *)NULL);
sigprocmask(SIG_SETMASK, &omask, (sigset_t *)NULL); /* Exec the shell. */
(void)execve("/bin/sh", (char *const *) new_argv, __environ);
/* execve通常不会返回, 返回就说明发生错误 */
_exit(127); /* 子进程返回状态码127 */
}
else if (pid < (pid_t) 0) {
/* fork()失败返回 -1 */
status = -1; /* 错误查看 errno */
}
else { /* 父进程 */
/* Note the system() is a cancellation point. But since we call
waitpid() which itself is a cancellation point we do not have to do anything here. */
if (waitpid(pid, &status, 0) != pid) {/* 子进程回收 */
status = -1; /* 错误查看 errno */
}
} /* 父进程信号处理恢复 */
sigaction(SIGINT, &intr, (struct sigaction *)NULL);
sigaction(SIGQUIT, &quit, (struct sigaction *)NULL);
sigprocmask(SIG_SETMASK, &omask, (sigset_t *)NULL); return status;
}
Linux下system()函数的实现的更多相关文章
- 对于linux下system()函数的深度理解(整理)
原谅: http://blog.sina.com.cn/s/blog_8043547601017qk0.html 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同 ...
- 转:对于linux下system()函数的深度理解(整理)
这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以为 ...
- 【C/C++】Linux下system()函数引发的错误
http://my.oschina.net/renhc/blog/54582 [C/C++]Linux下system()函数引发的错误 恋恋美食 恋恋美食 发布时间: 2012/04/21 11:3 ...
- (笔记)Linux下system()函数的深度理解(整理)
注:从其它地方转的非常好的一篇文章,值得深究! 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数 ...
- 关于linux下system()函数的总结
导读 曾经的曾经,被system()函数折磨过,之所以这样,是因为对system()函数了解不够深入.这里必须要搞懂system()函数,因为有时你不得不面对它. 先来看一下system()函数的简单 ...
- [转载]关于linux下system()函数的总结
1.曾经的曾经,被system()函数折磨过,之所以这样,是因为对system()函数了解不够深入.这里必须要搞懂system()函数,因为有时你不得不面对它. 2.先来看一下system()函数的简 ...
- Linux下system函数
http://www.jb51.net/article/40517.htm 浅析如何在c语言中调用Linux脚本 http://blog.csdn.net/koches/article/detai ...
- linux下syscall函数,SYS_gettid,SYS_tgkill
出处:http://blog.chinaunix.net/uid-28458801-id-4630215.html linux下syscall函数,SYS_gettid,SYS_tgkill ...
- Linux下c函数dlopen实现加载动态库so文件代码举例
dlopen()是一个强大的库函数.该函数将打开一个新库,并把它装入内存.该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的.这种机制使得在系统中添加或者删除一个模块时,都不需要重新编译了. ...
随机推荐
- nginx日志格式定义和nginx.conf配置模板说明
在http的功能里添加log_format模块,内容如下: log_format main escape=json '{ "@timestamp": "$time_iso ...
- nginx资料汇总
nginx docker 中的一些目录和 windows下是不同的, 静态内容目录: /usr/share/nginx/html 配置文件目录: /etc/nginx 日志输出目录: /var/log ...
- PHP代码审计之命令注入
命令注入 命令注入就是通过利用无验证变量构造特殊语句对服务器进行渗透. 注入的种类有很多,而不仅仅是SQL Injection. php常见注入有以下几种(常见:,常见!!): 命令注入 (Comma ...
- PHP中的数组
一.数组的基础 php数组的分类 按照下标的不同,php分为关联数组与索引数组: 索引数组:下标从零依次增长(以前那种) 关联数组:下标为字符串格式,每个下标字符串与数组的值一一关联对应(有点儿像对象 ...
- laravel-mix的安装
Laravel-mix的安装 Laravel Mix 是一款前端任务自动化管理工具,使用了工作流的模式对制定好的任务依次执行.Mix 提供了简洁流畅的 API,让你能够为你的 Laravel 应用定义 ...
- sonar服务搭建
1.下载安装包,我安装的是6.7.6版本 https://www.sonarqube.org/downloads/ 2.安装前的环境要求 JDK1.8+ 数据库,我用的是Mysql5.6版本 3. ...
- JAVA学习笔记(1)—— eclipse自动补全和主题及字体配置
1.自动补全功能 (1)打开 Eclipse -> Window -> Perferences (2)选择Java -> Editor -> Content Assist -& ...
- Day 18: 记filebeat内存泄漏问题分析及调优
ELK 从发布5.0之后加入了beats套件之后,就改名叫做elastic stack了.beats是一组轻量级的软件,给我们提供了简便,快捷的方式来实时收集.丰富更多的数据用以支撑我们的分析.但由于 ...
- stylus 实践
音乐分享: Broken Back - <Halcyon Birds> —————————————————————————————————————————————————————————— ...
- pycharm安装package时报错
在pycharm pip 包时,提示报错:module 'pip' has no attribute 'main' 原因:由于我的是pip 18.1 版本里没有main() 解决方法: 如不降级 pi ...