我正在阅读《操作系统》一书,发现该示例可以正常工作。我了解ps -elf | less
在做什么。 |
(管道)充当ps -elf
和less
命令之间的桥梁,并且将ps -elf
的输出作为less
的输入。
但是要深入了解shell命令,我想了解会是什么
ps -elf | grep "/usr" | wc –l
可以吗?
在这种情况下,有两个|
(管道),逻辑相同。但是我无法将其实现为一个有效的示例。如果您知道该怎么做,这对我来说很清楚。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int fds[2];
char buf[30];
pid_t pid1, pid2, pid;
int status, i;
/* create a pipe */
if (pipe(fds) == -1) {
perror("pipe");
exit(1);
}
/* fork first child */
if ( (pid1 = fork()) < 0) {
perror("fork");
exit(1);
}
if ( pid1 == 0 ) {
close(1); /* close normal stdout (fd = 1) */
dup2(fds[1], 1); /* make stdout same as fds[1] */
close(fds[0]); /* we don't need the read end -- fds[0] */
if( execlp("ps", "ps", "-elf", (char *) 0) < 0) {
perror("Child");
exit(0);
}
/* control never reaches here */
}
/* fork second child */
if ( (pid2 = fork()) < 0) {
perror("fork");
exit(1);
}
if ( pid2 == 0 ) {
close(0); /* close normal stdin (fd = 0)*/
dup2(fds[0],0); /* make stdin same as fds[0] */
close(fds[1]); /* we don't need the write end -- fds[1]*/
if( execlp("less", "less", (char *) 0) < 0) {
perror("Child");
exit(0);
}
/* control never reaches here */
}
/* parent doesn't need fds - MUST close - WHY? */
close(fds[0]);
close(fds[1]);
/* parent waits for children to complete */
for( i=0; i<2; i++) {
pid = wait(&status);
printf("Parent: Child %d completed with status %d\n", pid, status);
}
}
答案 0 :(得分:2)
在创建管道时,您需要从管道中的 last 命令开始,然后从该命令反向进行。这样,您启动的每个程序都在等待管道中先前命令的输出。如果从头开始,则第一个程序可以在有机会启动第二个程序之前完成,从而导致管道被关闭。
在这种情况下,您首先运行less
。这就是在等待尚未出现的输出。然后,您运行ps
,其输出将馈送到less
。
/* fork first child */
if ( (pid1 = fork()) < 0) {
perror("fork");
exit(1);
}
if ( pid1 == 0 ) {
close(0); /* close normal stdin (fd = 0)*/
dup2(fds[0],0); /* make stdin same as fds[0] */
close(fds[1]); /* we don't need the write end -- fds[1]*/
if( execlp("less", "less", (char *) 0) < 0) {
perror("Child");
exit(0);
}
/* control never reaches here */
}
/* fork second child */
if ( (pid2 = fork()) < 0) {
perror("fork");
exit(1);
}
if ( pid2 == 0 ) {
close(1); /* close normal stdout (fd = 1) */
dup2(fds[1], 1); /* make stdout same as fds[1] */
close(fds[0]); /* we don't need the read end -- fds[0] */
if( execlp("ps", "ps", "-elf", (char *) 0) < 0) {
perror("Child");
exit(0);
}
/* control never reaches here */
}