我正在试验Linux,目前我正在编写一个模拟Linux shell的程序。
我有一个主要的function,parsinginput和我的问题是不相关的现在。 在每一行被parsing后,调用处理所有内容的进程行方法。 目前,我支持常规进程和后台进程,目前正在处理仅包含2个命令(cmd1 | cmd2)的未命名pipe道。
这里是代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/wait.h> #include <unistd.h> void wait_for_background_process(void* arg) { int status; pid_t* pid = (pid_t*) arg; do { printf("Waiting for %dn",*pid); waitpid(*pid,&status,WUNTRACED); } while (!WIFEXITED(status) && !WIFSIGNALED(status)); } /************************ function: void pipeCommand(char** cmd1,char** cmd2) comment: This pipes the output of cmd1 into cmd2. **************************/ void pipe_command(char** cmd1,char** cmd2) { int fds[2]; // file descriptors if(pipe(fds) < 0) { perror("myShell"); exit(EXIT_FAILURE); } pid_t pid; pid = fork(); if(pid == 0) { dup2(fds[1],1); if(execvp(cmd1[0],cmd1) < 0) { perror("myShell"); exit(EXIT_FAILURE); } execvp(cmd1[0],cmd1); } else if(pid < 0) { perror("myShell"); exit(EXIT_FAILURE); } else { wait(NULL); dup2(fds[0],0); if(execvp(cmd2[0],cmd2)) { perror("myShell"); exit(EXIT_FAILURE); } } } /* * Checks if the command is pipe command,if so we will return the * index of the pipe */ int is_pipe_command(char** arglist,int count) { int i = 0; for(i = 0; i < count; i++) { if(strcmp(arglist[i],"|") == 0) { return i; } } return 0; } int process_arglist(int count,char** arglist) { pid_t pid; int pipe_index; pid = fork(); if (pid == 0) { // Child process if(strcmp(arglist[count-1],"&") == 0) { char** background_arglist = (char**) malloc((count)*sizeof(char*)); if(background_arglist == NULL) { printf("malloc Failed: %sn",strerror(errno)); exit(EXIT_FAILURE); } int i = 0; for(i = 0; i < count - 1; i++) { background_arglist[i] = arglist[i]; } background_arglist[count - 1] = NULL; if (execvp(background_arglist[0],background_arglist) == -1) { perror("myShell"); } } else if(pipe_index = is_pipe_command(arglist,count)) { char** cmd1 = (char**) malloc((pipe_index+1)*sizeof(char*)); if(cmd1 == NULL) { printf("malloc Failed: %sn",strerror(errno)); exit(EXIT_FAILURE); } int i; int cmd1index = 0; for(i = 0; i < pipe_index; i++) { cmd1[cmd1index] = arglist[i]; cmd1index++; } cmd1[pipe_index] = NULL; char** cmd2 = (char**) malloc((count - pipe_index)*sizeof(char*)); if(cmd2 == NULL) { printf("malloc Failed: %sn",strerror(errno)); exit(EXIT_FAILURE); } int cmd2index = 0; for(i = pipe_index+1; i < count; i++) { cmd2[cmd2index] = arglist[i]; cmd2index++; } cmd2[count-pipe_index-1] = NULL; pipe_command(cmd1,cmd2); } else { if (execvp(arglist[0],arglist) == -1) { perror("myShell"); } } exit(EXIT_FAILURE); } else if (pid < 0) { // Error forking perror("myShell"); exit(EXIT_FAILURE); } else { // Parent process if(strcmp(arglist[count-1],"&") == 0) { // The child is a background process pthread_t thread; pthread_create(&thread,NULL,wait_for_background_process,&pid); } else { // Regular process } } return 1; }
我们可以专注于pipe_command函数,它正确地得到2个命令,我不明白为什么我没有得到任何输出调用例如ls -l | sort ls -l | sort或ls -l | grep "a" ls -l | grep "a" 。
在C窗口fnmatch?
什么时候WM_PAINT被调用?
fgetpos()行为取决于换行符
只有磁盘写入,但iotop显示读取以及
在IE中调整由浏览器栏托pipe的Webbrowser控件的大小
谢谢。
你用什么工具在Windows上分析(本地)C ++?
如何使用Windows API检索HD供应商/串行
从Windows 8应用程序在Windows资源pipe理器中打开文件?
解决PE SxS导入Windows
在dup之后,你需要关闭fds[1] 。 否则第二个命令进程(在你的例子中sort或grep )不会从它的stdin读取得到一个EOF 。 EOF是需要的,以便过程知道何时停止处理和退出。
明确地说, pipe_command的else块应该像这样close :
} else { wait(NULL); dup2(fds[0],0); close(fds[1]); /* ADDED THIS LINE */ if(execvp(cmd2[0],cmd2)) { perror("myShell"); exit(EXIT_FAILURE); } }
还有一件事要注意。 通常第一个命令进程也需要类似的close(fds[0]); 。 但在你的情况下不需要,因为第二个进程在调用execvp之前等待第一个进程退出,这会导致第一个进程隐式关闭所有打开的文件描述符。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。