#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()函数的实现的更多相关文章

  1. 对于linux下system()函数的深度理解(整理)

    原谅: http://blog.sina.com.cn/s/blog_8043547601017qk0.html 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同 ...

  2. 转:对于linux下system()函数的深度理解(整理)

    这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以为 ...

  3. 【C/C++】Linux下system()函数引发的错误

    http://my.oschina.net/renhc/blog/54582 [C/C++]Linux下system()函数引发的错误 恋恋美食  恋恋美食 发布时间: 2012/04/21 11:3 ...

  4. (笔记)Linux下system()函数的深度理解(整理)

    注:从其它地方转的非常好的一篇文章,值得深究! 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数 ...

  5. 关于linux下system()函数的总结

    导读 曾经的曾经,被system()函数折磨过,之所以这样,是因为对system()函数了解不够深入.这里必须要搞懂system()函数,因为有时你不得不面对它. 先来看一下system()函数的简单 ...

  6. [转载]关于linux下system()函数的总结

    1.曾经的曾经,被system()函数折磨过,之所以这样,是因为对system()函数了解不够深入.这里必须要搞懂system()函数,因为有时你不得不面对它. 2.先来看一下system()函数的简 ...

  7. Linux下system函数

    http://www.jb51.net/article/40517.htm   浅析如何在c语言中调用Linux脚本 http://blog.csdn.net/koches/article/detai ...

  8. linux下syscall函数,SYS_gettid,SYS_tgkill

    出处:http://blog.chinaunix.net/uid-28458801-id-4630215.html     linux下syscall函数,SYS_gettid,SYS_tgkill  ...

  9. Linux下c函数dlopen实现加载动态库so文件代码举例

    dlopen()是一个强大的库函数.该函数将打开一个新库,并把它装入内存.该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的.这种机制使得在系统中添加或者删除一个模块时,都不需要重新编译了. ...

随机推荐

  1. 阿里云ECS服务器部署Node.js项目全过程详解

    本文详细介绍如何部署NodeJS项目到阿里云ECS上,以及本人在部署过程中所遇到的问题.坑点和解决办法,可以说是全网最全最详细的教程了.同时讲解了如何申请阿里云免费SSL证书,以及一台ECS服务器配置 ...

  2. Asp.net MVC 权限过滤器实现方法的最佳实践

    在项目开发中,为了安全.方便地判断用户是否有访问当前资源(Action)的权限,我们一般通过全局过滤器来实现. Asp.net MVC 页面中常见的权限判断使用过滤器主要在以下几种情况(根据权限判断的 ...

  3. 洛谷P1032 字串变换-题解

    https://www.luogu.org/problemnew/show/P1032--(题目传送) 好在数据范围很小,暴力一点也能过.思路较简单,按照所有规则,从第一位开始广搜. 注意:1.str ...

  4. spring Boot 入门--为什么用spring boot

    为什么用spring boot 回答这个问题不得不说下spring 假设你受命用Spring开发一个简单的Hello World Web应用程序.你该做什么? 我能想到一些 基本的需要.  一个项目 ...

  5. python通过套接字来发送接收消息

    案例如下: 1.启动一个服务端套接字服务 2.启动一个客户端套接字服务 3.客户端向服务端发送一个hello,服务端则回复一个word,并打印 参考地址:https://www.cnblogs.com ...

  6. Apache Hadoop 2.9.2 的快照管理

    Apache Hadoop 2.9.2 的快照管理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 快照相当于对目录做一个备份.并不会立即复制所有文件,而是指向同一个文件.当写入发生 ...

  7. Linux基础系统优化及常用命令

    # Linux基础系统优化及常用命令 [TOC] ## Linux基础系统优化 Linux的网络功能相当强悍,一时之间我们无法了解所有的网络命令,在配置服务器基础环境时,先了解下网络参数设定命令. - ...

  8. git下载/上传文件提示:git did not exit cleanly

    问题:git操作下载/上传文件,提示信息如下 TortoiseGit-git did not exit cleanly (exit code 1) TortoiseGit-git did not ex ...

  9. 20164305 徐广皓 Exp4 恶意代码分析

    实践目标 1.1是监控你自己系统的运行状态,看有没有可疑的程序在运行. 1.2是分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使用原生指令或sysinternals,systr ...

  10. grep sed awk 3个Linux中对文件内容操作的命令

    在学习Linux命令中,发现3个有关于文件内容操作的命令grep,sed和awk,在这里简单汇总这3个命令主要作用,在实际中找到最合适的情景应用,详细用法可以参考其他文章. 1.grep命令 主要作用 ...