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

歡迎訪問 生活随笔!

生活随笔

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

linux

Linux的system和popen的差异

發布時間:2024/1/23 linux 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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_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; }

上面是一個不算完整的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) {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.執行流程

? ? ? ?從上面的源碼可以看到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信號可以參考:https://blog.csdn.net/astrotycoon/article/details/40626355、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的原因可以繼續參考上面提到的https://blog.csdn.net/astrotycoon/article/details/40626355,popen()函數中沒有屏蔽SIGINT、SIGQUIT的原因也還是因為popen是"并行的",不能影響它"并行"進程。

5.功能

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

NOTE

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

?

轉自:https://blog.csdn.net/liuxingen/article/details/47057539

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

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

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