写在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");總結
以上是生活随笔為你收集整理的写在2019年来临前的倒数0.5小时的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第八届蓝桥杯(软件类)决赛C/C++B组
- 下一篇: 逻辑覆盖 测试题