日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux的system和popen的差异

發(fā)布時(shí)間:2024/1/23 linux 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux的system和popen的差异 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.system()和popen()簡介

在linux中我們可以通過system()來執(zhí)行一個(gè)shell命令,popen()也是執(zhí)行shell命令并且通過管道和shell命令進(jìn)行通信。

system()、popen()給我們處理了fork、exec、waitpid等一系列的處理流程,讓我們只需要關(guān)注最后的返回結(jié)果(函數(shù)的返回值)即可。

2.system()、popen()源碼

首先我們來看一個(gè)這兩個(gè)函數(shù)在源碼(偽代碼)上面的差異。

int system(const char *command) {struct sigaction sa_ignore, sa_intr, sa_quit;sigset_t block_mask, orig_mask;pid_t pid;sigemptyset(&block_mask);sigaddset(&block_mask, SIGCHLD);sigprocmask(SIG_BLOCK, &block_mask, &orig_mask); //1.block SIGCHLDsa_ignore.sa_handler = SIG_IGN;sa_ignore.sa_flags = 0;sigemptyset(&sa_ignore.sa_mask);sigaction(SIGINT, &sa_ignore, &sa_intr); //2.ignore SIGINT signalsigaction(SIGQUIT, &sa_ignore, &sa_quit); //3.ignore SIGQUIT signalswitch((pid = fork())) {case -1:return -1;case 0:sigaction(SIGINT, &sa_intr, NULL);sigaction(SIGQUIT, &sa_quit, NULL);sigprocmask(SIG_SETMASAK, &orig_mask, NULL);execl("/bin/sh", "sh", "-c", command, (char *)0);exit(127);default:while(waitpid(pid, NULL, 0) == -1) { //4.wait child process exitif (errno != EINTR) {break;}}}return 0; }

上面是一個(gè)不算完整的system函數(shù)源碼,后面需要我們關(guān)注和popen差異的部分已經(jīng)用數(shù)字標(biāo)識(shí)出來了。

static pid_t *childpid = NULL; /* ptr to array allocated at run-time */static int maxfd; /* from our open_max(), {Prog openmax} */#define SHELL "/bin/sh"FILE * popen(const char *cmdstring, const char *type) {int i, pfd[2];pid_t pid;FILE *fp;/* only allow "r" or "w" */if ((type[0] != 'r' && type[0] != 'w') || type[1] != 0) {errno = EINVAL; /* required by POSIX.2 */return (NULL);}if (childpid == NULL) { /*first time through *//*allocate zeroed out array for child pids */maxfd = open_max();if (( childpid = calloc(maxfd, sizeof(pid_t))) == NULL)return (NULL);}if (pipe(pfd) < 0)return (NULL); /*errno set by pipe() */if ((pid = fork()) < 0) return (NULL); /*errno set by fork() */else if (pid == 0) {if (*type == 'r') {close(pfd[0]);if (pfd[1] != STDOUT_FILENO) {dup2(pfd[1], STDOUT_FILENO);close(pfd[1]);}} else {close(pfd[1]);if (pfd[0] != STDIN_FILENO) {dup2(pfd[0], STDIN_FILENO);close(pfd[0]);}}/*close all descriptors in childpid[]*/for (i=0; i<maxfd; i++)if (childpfd[i] > 0) close(i);execl(SHELL, "sh", "-c", cmdstring, (char *)0);_exit(127);}/*parent*/if (*type == 'r') {close(pfd[1]);if ((fp = fdopen(pfd[0], type)) == NULL) return (NULL);} else {close(pfd[0]);if ((fp = fdopen(pfd[1], type)) == NULL)return (NULL);}childpid[fileno(fp)] = pid; /*remember child pid for this fd*/return (fp); }

上面是popen的源碼。

3.執(zhí)行流程

? ? ? ?從上面的源碼可以看到system和popen都是執(zhí)行了類似的運(yùn)行流程,大致是fork->execl->return。但是我們看到system在執(zhí)行期間調(diào)用進(jìn)程會(huì)一直等待shell命令執(zhí)行完成(waitpid等待子進(jìn)程結(jié)束)才返回,但是popen無須等待shell命令執(zhí)行完成就返回了。我們可以理解system為串行執(zhí)行,在執(zhí)行期間調(diào)用進(jìn)程放棄了"控制權(quán)",popen為并行執(zhí)行。

? ? ? ?popen中的子進(jìn)程沒人給它“收尸”了啊?是的,如果你沒有在調(diào)用popen后調(diào)用pclose那么這個(gè)子進(jìn)程就可能變成"僵尸"。

? ? ? ?上面我們沒有給出pclose的源碼,其實(shí)我們根據(jù)system的源碼差不多可以猜測出pclose的源碼就是system中第4部分的內(nèi)容。

4.信號處理

我們看到system中對SIGCHLD、SIGINT、SIGQUIT都做了處理,但是在popen中沒有對信號做任何的處理。

SIGCHLD是子進(jìn)程退出的時(shí)候發(fā)給父進(jìn)程的一個(gè)信號,system()中為什么要屏蔽SIGCHLD信號可以參考:https://blog.csdn.net/astrotycoon/article/details/40626355、waitpid(or wait)和SIGCHILD的關(guān)系,總結(jié)一句就是為了system()調(diào)用能夠及時(shí)的退出并且能夠正確的獲取子進(jìn)程的退出狀態(tài)(成功回收子進(jìn)程)。

popen沒有屏蔽SIGCHLD,主要的原因就是popen是"并行"的。如果我們在調(diào)用popen的時(shí)候屏蔽了SIGCHLD,那么如果在調(diào)用popen和pclose之間調(diào)用進(jìn)程又創(chuàng)建了其他的子進(jìn)程并且調(diào)用進(jìn)程注冊了SIGCHLD信號處理句柄來處理子進(jìn)程的回收工作(waitpid),那么這個(gè)回收工作就會(huì)一直阻塞到pclose調(diào)用。這也意味著如果調(diào)用進(jìn)程在pclose之前執(zhí)行了一個(gè)wait()操作的話就可能獲取到popen創(chuàng)建的子進(jìn)程的狀態(tài),這樣在調(diào)用pclose的時(shí)候就會(huì)回收(waitpid)子進(jìn)程失敗,返回-1,同時(shí)設(shè)置errno為ECHLD,標(biāo)識(shí)pclose無法獲取子進(jìn)程狀態(tài)。

system()中屏蔽SIGINT、SIGQUIT的原因可以繼續(xù)參考上面提到的https://blog.csdn.net/astrotycoon/article/details/40626355,popen()函數(shù)中沒有屏蔽SIGINT、SIGQUIT的原因也還是因?yàn)閜open是"并行的",不能影響它"并行"進(jìn)程。

5.功能

從上面的章節(jié)我們基本已經(jīng)把這兩個(gè)函數(shù)剖析的差不多了,這兩個(gè)的功能上面的差異也比較明顯了,system就是執(zhí)行shell命令最后返回是否執(zhí)行成功,popen執(zhí)行并且通過管道和shell命令進(jìn)行通信。

NOTE

在特權(quán)(setuid、setgid)進(jìn)程中千萬注意不要使用system和popen。

?

轉(zhuǎn)自:https://blog.csdn.net/liuxingen/article/details/47057539

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的Linux的system和popen的差异的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 麻豆传媒在线观看视频 | 国产一卡二卡在线 | 国产91边播边对白在线 | japanese国产在线观看 | 久久天天躁狠狠躁夜夜躁2014 | 少妇4p | 动漫av在线| 久久精品香蕉 | 亚洲www久久久 | 无码一区二区波多野结衣播放搜索 | 18禁免费观看网站 | 成人先锋av | 九九热在线观看 | 碰碰97 | 91视频亚洲 | 国产精品久久综合青草亚洲AV | 999久久精品 | 亚洲欧美日韩在线不卡 | 丰满肉肉bbwwbbww | 久久精品香蕉视频 | 99国产精品久久久久 | 国产成人资源 | 国产黄色片免费在线观看 | 制服丝袜影音先锋 | 毛片网在线观看 | 黄色激情视频网站 | 波多在线播放 | 国产又粗又黄又爽又硬的视频 | 自拍偷自拍亚洲精品播放 | 日韩黄色a级片 | 一级黄色片网址 | 香蕉视频黄色片 | 在线99视频 | 日韩在线视频你懂的 | 国产另类xxxxhd高清 | 西野翔之公侵犯中文字幕 | 黄色大片毛片 | 日韩欧美一区二区三区视频 | 九九热视频这里只有精品 | 在线欧美激情 | 久久99精品国产.久久久久久 | 亚洲久久久久久 | 精品国产乱码久久久久久预案 | 在线视频观看国产 | 97国产成人无码精品久久久 | 亚洲成人一二三区 | 青青草国产一区 | 飘花影院伦理片 | 日夜夜操| 男女三级视频 | 少妇又白又嫩又色又粗 | 第一次破处视频 | 久久黄色录像 | 女女互磨互喷水高潮les呻吟 | 91爱视频 | 日韩视频福利 | 丁香激情五月少妇 | 嫩嫩av| 成人黄色在线视频 | 国产视频四区 | 黄色精品一区二区 | 亚洲成人精品视频 | 午夜精品久久久久久久99热浪潮 | 一本大道久久久久精品嫩草 | 五月婷婷婷 | 朝桐光一区二区三区 | av网址导航 | 欧美不卡三区 | 337p粉嫩色噜噜噜大肥臀 | 亚洲视频精品在线观看 | 日韩欧美高清在线 | 欧美一级在线免费 | 黄色三级小视频 | 免费高清毛片 | 欧美精品电影一区二区 | 叶爱在线 | 国产人成在线观看 | 无码h黄肉3d动漫在线观看 | 中国一级特黄录像播放 | 草比网站 | 欧洲久久精品 | 秋霞午夜视频 | 91视频地址 | 久久午夜精品人妻一区二区三区 | 欧美一区二区日韩一区二区 | 久久国产精品一区二区 | 久久草网站| 男人狂揉女人下部视频 | 日韩阿v | 国产一区二区三区精品在线观看 | 明里柚番号 | 日韩大片免费 | 免费的理伦片在线播放 | 精品久久久久久久久中文字幕 | 欧美肉丝袜videos办公室 | 免费在线小视频 | 懂色a v| wwwxxx色| 欧洲成人综合 |