写在2019年来临前的倒数0.5小时

本来这篇文章是晚饭前要发表的,想完整的把system()函数和Linux系统上的信号梳理清晰,不料傍晚有点事情离开了一会儿,回来后又在楼下换了个新发型,耽误了好多时间,回来时已经是11点了。迅速洗澡洗衣服,把中午写到一段落的这篇文章发表出来:这是2018年最后1篇博文,先把system()基础梳理清晰,然后2019的第1篇文章就继续system()和信号的关系。

匆匆2018年就这样要过去了,如果要为这消逝的365天加以概括,我觉得平平淡淡吧,无惊喜也无意外。工作上能够做自己意向的Linux C/C++开发且技术上能循序渐进;生活中能分担家里经济负担,供妹妹上大学后,自己衣食住行不愁。这也是亲戚朋友眼中的我。

事实上可能随着年纪的增长,有些忧虑忧患也应运而生。看着身边的朋友生小孩的生小孩,结婚的结婚的,脱单的脱单,有时候自己也稍微也紧张了起来。这种感觉就像一群小学生的期末考,其它同学纷纷答卷完毕并递交试卷了,而我还没开始答题。也有这么一两个好友他们答题完毕了还不急着起身走出教室,甚至好心偷偷丢纸条给我,那是试题答案,可我可能比较轴,我想自己答题所以谢绝了这样的纸条。

2016年6月份毕业到现在不知不觉业已2年多了,一开始出来心无旁骛,一心只想扎进码农的圈子,然后拿到能拿到一份丰硕的薪资,那时候每天都精力澎湃的学习,眨巴眨巴时间过去了,当初的目标渐渐靠近的同时也产生了新的目标,却也发现很多目标即使达到了也不能让自己快乐多少,比如你费尽心机攻破一个系统编程问题或者加班加点解决了客户的现场问题,心里如释重负的同时,退下来却发现身边没有一个可以跟你分享喜悦的人;再者你拿到你规划的薪资,发现这份薪资依旧是“刚刚可以过”,努力奋斗的回报无非使能过稍微正常点的生活

这几天的深圳特别冷啊,最低都达到了9℃,听北方的同事说他们家乡都下雪了,对我这个从未走出广东,甚至深圳隔壁的香港都没涉足过的人来说,走进一场大雪是一种什么样的奇妙经历?想象不到。2019的愿望:希望能有那么一个人跟我涉足北方城市,一起经历一场大雪

ok,接下来进入正题,来分析一下Linux系统上的system()函数。

程序设计中system()用于执行shell命令,如我们要时间和日期写入某个文件:

system("sh data > file");

system()的函数原型如下:

#include <stdlib.h>
int system(const char *command);

system()的实现:fork()创建一个子进程,并将传入的参数调用execl()函数:

execl("/bin/sh", "sh", "-c", command, (char* )NULL);

为获取system()所创建的子进程状态,还需要调用waitpid(),所以system()的初步实现:

#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdlib.h>
#include "system_test.h"
#include <errno.h>

int system_test(char* command)
{
	pid_t cpid = -1;
	int status;

	switch (cpid = fork()) {
		case -1:
			perror("fork");
			return -1;
		
		case 0:
			execl("/bin/sh", "sh", "-c", command, (char* )NULL);
			_exit(127);

		default:
			while (waitpid(cpid, &status, 0) == -1) {
				if (errno == EINTR) {		/* 被信号中断时继续回去等待,重要 */
					continue;
				}

				perror("waitpid");
				return -1;
			}
			
			return status;
			
	}
}

int main(void)
{
	system_test("date");
	return 0;
}

运行:
在这里插入图片描述
需要注意:
(1) -c选项的作用:告诉shell程序读取下一个命令行参数作为命令输入,而不是从标准输入或者从一个给定的文件中读取命令;
(2)代码调用的是_exit()而非exit(),目的在于防止任一标准I/O缓冲在子进程中被冲洗。
上面代码看似简单,实际上system()的实现还需要考虑到信号。在APUE一书中说到:

POSIX.1要求system()忽略SIGINT和SIGQUIT,阻塞SIGCHLD信号。

这里说到“忽略”和“阻塞”,什么意思:
阻塞:内核会为每个进程维护一组信号,也称之为掩码。在该组的信号将阻塞对所在进程的传递。假设进程A将信号xx放到信号掩码中,当外界(可能是内核,也可能是其他进程)向进程A发xx信号,那么该信号将被延后,直至从进程A的掩码中移除xx信号。使用sigprocmask()系统调用可以显式向信号掩码中添加移除信号。
忽略:某进程忽略了某信号,若该信号专为该进程而生,那么内核会自行将其丢弃,内核甚至从未知道曾经产生了该信号。使用signal()或者sigaction()系统调用设置信号的对应操作为SIG_IGN忽略了该信号。

为什么要忽略SIGINT和SIGQUIT,阻塞SIGCHLD信号,且看下文…

最后让我们静待2019的来临吧,希望2019年大家快乐:

system("echo 'Happy2019' >> 2019.year");

在这里插入图片描述

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值