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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux的system()和popen()差异

發布時間:2025/3/15 linux 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux的system()和popen()差异 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Linux的system()和popen()差異


1. system()和popen()簡介

在Linux中我們可以通過system()來執行一個shell命令,popen()也是執行shell命令并且通過管道和shell命令進行通信。?
system()、popen()給我們處理了fork、exec、waitpid等一系列的處理流程,讓我們只需要關注最后的返回結果(函數的返回值)即可。

2. system()、popen()源碼

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

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_SETMASK, &orig_mask, NULL);execl("/bin/sh", "sh", "-c", command, (char *) 0);exit(127);default:while(waitpid(pid, NULL, 0) == -1) //4. wait child process exit{if(errno != EINTR){break;}}} } return 0;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

上面是一個不算完整的system函數源碼,后面需要我們關注和popen差異的部分已經用數字標示出來了。

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) { /* child */ 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 (childpid[ 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); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66

上面是popen的源碼。

3. 執行流程

從上面的源碼可以看到system和popen都是執行了類似的運行流程,大致是fork->execl->return。但是我們看到system在執行期間調用進程會一直等待shell命令執行完成(waitpid等待子進程結束)才返回,但是popen無須等待shell命令執行完成就返回了。我們可以理解system為串行執行,在執行期間調用進程放棄了”控制權”,popen為并行執行。?
popen中的子進程沒人給它”收尸”了啊?是的,如果你沒有在調用popen后調用pclose那么這個子進程就可能變成”僵尸”。?
上面我們沒有給出pclose的源碼,其實我們根據system的源碼差不多可以猜測出pclose的源碼就是system中第4部分的內容。

4. 信號處理

我們看到system中對SIGCHLD、SIGINT、SIGQUIT都做了處理,但是在popen中沒有對信號做任何的處理。?
SIGCHLD是子進程退出的時候發給父進程的一個信號,system()中為什么要屏蔽SIGCHLD信號可以參考:system函數的總結、waitpid(or wait)和SIGCHILD的關系,總結一句就是為了system()調用能夠及時的退出并且能夠正確的獲取子進程的退出狀態(成功回收子進程)。?
popen沒有屏蔽SIGCHLD,主要的原因就是popen是”并行”的。如果我們在調用popen的時候屏蔽了SIGCHLD,那么如果在調用popen和pclose之間調用進程又創建了其它的子進程并且調用進程注冊了SIGCHLD信號處理句柄來處理子進程的回收工作(waitpid)那么這個回收工作會一直阻塞到pclose調用。這也意味著如果調用進程在pclose之前執行了一個wait()操作的話就可能獲取到popen創建的子進程的狀態,這樣在調用pclose的時候就會回收(waitpid)子進程失敗,返回-1,同時設置errno為ECHLD,標示pclose無法獲取子進程狀態。?
system()中屏蔽SIGINT、SIGQUIT的原因可以繼續參考上面提到的system函數的總結,popen()函數中沒有屏蔽SIGINT、SIGQUIT的原因也還是因為popen是”并行的”,不能影響其它”并行”進程。

4. 功能

從上面的章節我們基本已經把這兩個函數剖析的差不多了,這兩個的功能上面的差異也比較明顯了,system就是執行shell命令最后返回是否執行成功,popen執行命令并且通過管道和shell命令進行通信。

NOTE

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

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 青青草国产在线视频 | 69视频免费观看 | 一级二级三级黄色片 | 久久精品无码一区二区三区 | 91精品国产欧美一区二区 | 亚洲欧美日韩国产成人精品影院 | 久久久久亚洲AV成人 | 免费人成视频在线 | 成年人免费网站 | たちの熟人妻av一区二区 | 国产精品99久久久 | www.在线看| 欧美精品在线视频观看 | 黄色小网站入口 | 成人欧美一区二区三区黑人孕妇 | 91精品久久久久久粉嫩 | 久久福利网站 | 一区二区不卡免费视频 | 亚洲精品乱码久久久久久不卡 | 一区二区三区四区免费视频 | 国产在线视频一区 | 国产午夜福利一区二区 | 已满十八岁免费观看全集动漫 | 无码无套少妇毛多18pxxxx | 日韩a级一片 | 激情五月色婷婷 | 69久人妻无码精品一区 | 日本欧美国产在线 | 伊人222成人综合网 亚洲日本中文 | 色偷偷网 | 二区视频在线观看 | 天天影视插插插 | 欧美一级在线视频 | 四色永久访问 | 亚洲精品视频一区二区三区 | 亚洲GV成人无码久久精品 | 亚洲av电影天堂男人的天堂 | 超碰加勒比 | 一区二区91 | 北条麻妃久久精品 | 想要视频在线观看 | 国产精品国产三级国产普通话蜜臀 | 欧美日韩精品一二三区 | 日本在线一区二区三区 | 精品国产乱码一区二区三 | 成年人av电影 | 我们好看的2018视频在线观看 | 欲色av| 亚洲精品1区 | 诱惑の诱惑筱田优在线播放 | 男女视频免费看 | 极品美妇后花庭翘臀娇吟小说 | 午夜影院福利 | 伊人色播 | 一区二区三区四区在线观看视频 | 午夜高潮视频 | 婷婷综合在线观看 | 青青青在线免费观看 | 国产亚洲精品成人av久久ww | 日本美女性高潮 | 日韩精品一区二区亚洲av观看 | 毛片在线网站 | 91久久一区二区 | 黄色在线观看网址 | 制服丝袜一区在线 | 亚洲专区在线 | 乌克兰做爰xxxⅹ性视频 | 亚洲精品污一区二区三区 | av在线电影观看 | 91国产中文字幕 | 狠狠的干狠狠的操 | 欧美激情精品 | 999午夜 | 瑟瑟视频在线免费观看 | 九九爱精品 | 老司机午夜免费福利 | 日韩视频在线观看一区二区 | 杨幂毛片午夜性生毛片 | 自拍偷拍亚洲精品 | 视频网站在线观看18 | 男女视频在线观看 | 国产视频在线观看免费 | 豆花视频在线播放 | 97人妻精品一区二区三区视频 | 日本一级片免费看 | 可以看污的网站 | 色94色欧美| 黑人又大又粗又长 | 人成精品 | 黄瓜视频91 | 91精品视频免费看 | 青青草原国产在线 | 国产美女精品人人做人人爽 | 国产精品天美传媒 | 欧美日本一区二区三区 | 久久av影院 | 国产六区| 亚洲最新av | 黄色日比视频 |