C 定制linux shell中的管道
尝试用一些基本函数实现我自己的linux shell,当然,在实现管道时会出现一个问题。更具体地说,管道在很大程度上起作用,尽管它似乎放弃了最后一个论点。例如,如果我要运行命令C 定制linux shell中的管道,c,linux,pipe,C,Linux,Pipe,尝试用一些基本函数实现我自己的linux shell,当然,在实现管道时会出现一个问题。更具体地说,管道在很大程度上起作用,尽管它似乎放弃了最后一个论点。例如,如果我要运行命令 ps ax | grep ps grep命令后的ps被放入我的shell中。因此,不要像使用典型的Linux shell那样输出它 339 ? S 0:00 upstart-udev-bridge --daemon 497 ? Ss 0:00 /usr/sbin/cupsd
ps ax | grep ps
grep命令后的ps被放入我的shell中。因此,不要像使用典型的Linux shell那样输出它
339 ? S 0:00 upstart-udev-bridge --daemon
497 ? Ss 0:00 /usr/sbin/cupsd -F
503 ? S< 0:00 [kpsmoused]
720 ? S 0:00 upstart-socket-bridge --daemon
5541 pts/0 R+ 0:00 ps ax
5542 pts/0 S+ 0:00 grep --colour=auto ps
339?S 0:00 upstart udev桥--守护进程
497 ? Ss 0:00/usr/sbin/cupsd-F
503 ? S<0:00[kps已用]
720 ? S 0:00 upstart套接字桥--守护进程
5541分/0 R+0:00 ps ax
5542分/0s+0:00grep--color=auto-ps
你明白了吗
339 ? S 0:00 upstart-udev-bridge --daemon
497 ? Ss 0:00 /usr/sbin/cupsd -F
503 ? S< 0:00 [kpsmoused]
720 ? S 0:00 upstart-socket-bridge --daemon
5557 pts/0 R+ 0:00 ps ax
339?S 0:00 upstart udev桥--守护进程
497 ? Ss 0:00/usr/sbin/cupsd-F
503 ? S<0:00[kps已用]
720 ? S 0:00 upstart套接字桥--守护进程
5557分/0 R+0:00 ps ax
在这种情况下,您不是在搜索匹配的模式ps
管道管路的功能如下所示
void mypipes(char* args[], int nargs)
{
pid_t pid;
int fd[2];
char* cmdargs[nargs - 2];
char* cmdargs2[nargs - 2];
int i;
int t = 0;
int count = 0;
for(i = 0; i < nargs; i++)
{
if(!strcmp(args[i], "|"))
{
//dont put into array
t = 1;
}
else if(t == 0)
{
cmdargs[i] = args[i];
count++;
}
else if(t == 1)
{
cmdargs2[i - 3] = args[i];
}
}
if(count == 2)
{
pipe(fd);
pid = fork();
if(pid == -1)
{
perror("unable to fork");
exit(1);
}
if(pid > 0)
{
wait(&pid);
close(fd[1]);
close(0);
dup2(fd[0],0);
execlp(cmdargs2[0], cmdargs2[0], cmdargs2[1], NULL);
}
if(pid == 0)
{
close(fd[0]);
close(1);
dup2(fd[1],1);
execlp(cmdargs[0], cmdargs[0], cmdargs[1], NULL);
}
}
if(count == 1)
{
pipe(fd);
pid = fork();
if(pid == -1)
{
perror("unable to fork");
exit(1);
}
if(pid > 0)
{
wait(&pid);
close(fd[1]);
close(0);
dup2(fd[0],0);
execlp(cmdargs2[0], cmdargs2[1], NULL);
}
if(pid == 0)
{
close(fd[0]);
close(1);
dup2(fd[1],1);
execlp(cmdargs[0], cmdargs[1], NULL);
}
}
}
void mypipes(char*args[],int nargs)
{
pid_t pid;
int-fd[2];
char*cmdargs[nargs-2];
char*cmdargs2[nargs-2];
int i;
int t=0;
整数计数=0;
对于(i=0;i0)
{
等待(&pid);
关闭(fd[1]);
关闭(0);
dup2(fd[0],0);
execlp(cmdargs2[0],cmdargs2[0],cmdargs2[1],NULL);
}
如果(pid==0)
{
关闭(fd[0]);
关闭(1);
dup2(fd[1],1);
execlp(cmdargs[0],cmdargs[0],cmdargs[1],NULL);
}
}
如果(计数=1)
{
管道(fd);
pid=fork();
如果(pid==-1)
{
佩罗尔(“无法叉叉”);
出口(1);
}
如果(pid>0)
{
等待(&pid);
关闭(fd[1]);
关闭(0);
dup2(fd[0],0);
execlp(cmdargs2[0],cmdargs2[1],NULL);
}
如果(pid==0)
{
关闭(fd[0]);
关闭(1);
dup2(fd[1],1);
execlp(cmdargs[0],cmdargs[1],NULL);
}
}
}
我已经检查了管道后面的所有变量是否仍然在第二组参数中,并且它们是唯一的问题不是主参数,而是在我执行实际管道的某个地方,它没有读到最后
首先,除非我遗漏了什么,否则您的两个示例输出看起来都正常工作:它们都只列出了带有“ps”的行。(如果它真的在运行
ps ax | grep
,那么grep
会抱怨使用情况)。我在输出中看到的唯一区别是第二个没有列出grep
进程本身,但是如果ps
在grep
启动之前抓取完进程列表,这很容易发生
其次,您对wait(&pid)
的使用很奇怪,因为它在子进程中,它将等待子进程的任何子进程退出。由于没有,它将返回ECHILD
(如果有,它将用孙子的退出状态覆盖pid
)
第三,您可以使用t
、cmdargs
和cmdargs2
以及count
来决定只进行execlp
调用的cmd1 arg1 | cmd2 arg2
形式的调用——几乎任何其他组合都不起作用。有两点:
- 您需要记住看到管道的位置,而不是
来保存管道后的参数(例如,在找到管道时使用[i-3]
,在保存管道后的参数时使用t=i+1
)cmdargs2[i-t]
- 您需要查看函数调用的
版本,以便传入参数数组(记住在命令行的所有参数之后添加NULL元素)execvp()