在c中使用管道执行命令
我一直在尝试制作一个程序,它可以读取shell命令并像以前一样执行它们在c中使用管道执行命令,c,process,pipe,fork,C,Process,Pipe,Fork,我一直在尝试制作一个程序,它可以读取shell命令并像以前一样执行它们 ls -l | sort > there.txt 然而,我所做的似乎并不是在执行第二个命令。 我还是c编程新手,对fork()和pipe()一点都不熟悉,所以如果我所做的有很多错误,我也不会感到惊讶。 如果有人能帮忙,我将不胜感激。 先谢谢你 这是我的密码: 普通的 #include <stdlib.h> #include <stdio.h> #include <string.h>
ls -l | sort > there.txt
然而,我所做的似乎并不是在执行第二个命令。
我还是c编程新手,对fork()和pipe()一点都不熟悉,所以如果我所做的有很多错误,我也不会感到惊讶。
如果有人能帮忙,我将不胜感激。
先谢谢你
这是我的密码:
普通的
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
void runThat(char* cmd1[], char* cmd2[]);
我也编辑了我的主类,但我测试了它,没有任何问题,所以下面的代码肯定又出了问题。它应该能够在没有管道或多条管道的情况下运行
void runThat(char *cmds[][MAX_PAR], int NOP){
pid_t pid, waitPid;
int status;
int pipefd[2];
int Num_Cmds = NOP +1;
int r[Num_Cmds]; int w[Num_Cmds];
char ** cmd;
for (int i = 0; i < Num_Cmds; i++){
r[i] = -1;
w[i] = -1;
}
for (int j = 0; j < NOP; j++){
pipe(pipefd);
r[j+1] = pipefd[0];
w[j] = pipefd[1];
}
for (int i = 0; i < Num_Cmds; i++){
int h = 0;
while (cmds[i][h]!= NULL){
cmd[h] = cmds[i][h];
printf("This [%s]\n", cmd[h]);
h++;
}
cmd[h] = NULL;
printf("This [%s]\n", cmd[h]);
if (pid = fork() < 0){
perror("Fork has failed");
exit(1);
}
else if(pid == 0){
if (r[i] != -1){
close(STDIN_FILENO);
dup2(r[i],STDIN_FILENO);
}
if (w[i] != -1){
close(STDOUT_FILENO);
dup2(w[i],STDOUT_FILENO);
}
for (int j = 0; j < Num_Cmds; j++){
close(w[j]);
close(r[j]);
}
if (execvp(cmd[0], cmd)==-1){
perror("Command Failed");
exit(0);
}
}
else{
waitPid = wait(&status);
if (waitPid == -1){
perror("Waitpid failed");
exit(1);
}
close(w[i]);
if (i>0){
close(r[i]);
}
}
}
}
void runThat(char*cmds[][MAX\u PAR],int NOP){
pid_t pid,waitPid;
智力状态;
int-pipefd[2];
int Num_Cmds=NOP+1;
int r[Num_Cmds];int w[Num_Cmds];
字符**cmd;
对于(int i=0;i0){
闭(r[i]);
}
}
}
}
(1)我没有看到任何代码可以打开there.txt
,并将其设置为第二个进程的标准输出。(2) 要构建管道,必须在等待任何进程之前启动所有进程;否则你可能会陷入僵局。(3) 一般来说,对于这样的问题,我们希望看到一个完整的程序,我们可以自己编译、运行和修补。请阅读。这不是您当前的问题,但您没有在第一个子项中关闭足够的管道文件描述符。经验法则:如果使用dup()
或dup2()
将管道的一端重定向到标准输入或输出,则应关闭管道的两端。在某些情况下,您可能不需要这样做,但它们很少。(在本例中这是否重要是另一个讨论。)此外,不需要测试execvp()
是否失败。如果它返回,则失败。(如果成功,另一个进程正在运行,永远不要返回此代码。)@zwol如果这是一个愚蠢的问题,请原谅我,但我如何真正知道我的进程是否正在运行。这是我到目前为止还没有弄明白的事情…@Sakis当fork
成功的时候,有两个进程,它们都在运行。@zwol你知道有什么好的来源可以让我读更多关于fork和pipes的书吗?我找到了一些关于C的书,但没有一本是关于C的。
#include "common.h"
#define BUFFER 300
int main(void){
char * buffer = (char*)malloc(sizeof(char)* BUFFER);
unsigned int buffer_length;
char* tkn;
char * param[BUFFER];
char * cmd1[BUFFER];
char * cmd2[BUFFER];
char *filename = NULL;
char *output = NULL;
int append = 0;
int f1;
int f2;
int saved_stdin = dup(0);
int saved_stdout = dup(1);
printf("mysh4> ");
while (1){
filename = NULL;
output = NULL;
memset(buffer,0,BUFFER);
int input = getline(&buffer,&buffer_length,stdin);
if (input==-1){
printf("\n");
exit(1);
}
if (input>BUFFER){
printf("Error. Comand must not exceed %d characters.\n",BUFFER);
exit(1);
}
switch(input){
case 1:
printf("mysh4> ");
break;
default:
if ((strcmp(buffer,"exit\n")==0)||(strcmp(buffer,"terma\n")==0)||(strcmp(buffer,"end\n")==0)) {
printf("EXIT\n");
exit(1);
}
else {
int i =0; int j=0;
tkn = strtok(buffer," \t\n");
int NOP = 0;
while (tkn != NULL){
if(strcmp(tkn,"<")==0){
filename = tkn = strtok(NULL," \t\n");
}
else if(strcmp(tkn,">")==0){
output = tkn = strtok(NULL," \t\n");
append =0;
}
else if(strcmp(tkn,">>")==0){
output = tkn = strtok(NULL," \t\n");
append =1;
}
if(strcmp(tkn,"|")==0){
NOP++;
//param[i++] = NULL;
}
//else
param[i++] = tkn;
tkn = strtok(NULL, " \t\n");
}
param[i] = NULL;
i=0; j=0;
while (param[i]!= NULL){
if (strcmp(param[i],"|")==0) break;
cmd1[i] = param[i];
i++;
}
cmd1[i] = NULL;
while (param[i]!=NULL){
if (strcmp(param[i],"|")==0) i++;
cmd2[j] = param[i];
j++; i++;
}
cmd2[j] = NULL;
i=0;
while (cmd1[i]!=NULL){
printf("cmd1 HAS:[%s]\n", cmd1[i++]); // TO BE DELETED
if (cmd1[i]==NULL){
printf("cmd1 HAS:[NULL]\n");
}
}
i=0;
while (cmd2[i]!=NULL){
printf("cmd2 HAS:[%s]\n", cmd2[i++]); // TO BE DELETED
if (cmd2[i]==NULL){
printf("cmd2 HAS:[NULL]\n");
}
}
printf("FILENAME :[%s]\n", filename);
printf("OUTPUT: [%s]\n", output);
if (filename){
f1 = open(filename,O_APPEND | O_RDONLY);
if(dup2(f1,0) < 0) {
perror("Dup2:Input failed."); exit(1);
}
close(f1);
}
if (output){
if(append == 0)
f2 = open(output,O_WRONLY | O_CREAT | O_TRUNC, 0777);//TRUNC:ta sbhnei
else
f2 = open(output,O_WRONLY | O_CREAT | O_APPEND, 0777);
if(dup2(f2,1) < 0) {
perror("Dup2:Output failed."); exit(1);
}
close(f2);
}
runThat(cmd1,cmd2);
dup2(saved_stdin,0);
dup2(saved_stdout,1);
printf("mysh4> ");
break;
}//else
}//switch
}//while
free(buffer);
return 0;
}
total 40
-rw-rw-r-- 1 csuser csuser 1553 Μάι 12 18:27 common.c
-rw-rw-r-- 1 csuser csuser 313 Μάι 12 17:00 common.h
-rwxrwxr-x 1 csuser csuser 12204 Μάι 12 18:25 m
-rw-rw-r-- 1 csuser csuser 2534 Μάι 12 18:00 mysh4.c
-rw-rw-r-- 1 csuser csuser 7395 Μάι 12 12:44 p3090278-mysh4.c
-rwxrwxr-x 1 csuser csuser 59 Μάι 12 17:46 that
-rwxrwxr-x 1 csuser csuser 22 Μάι 12 18:13 there
csuser@CSLAB2:~/Desktop$ total 40
-rw-rw-r-- 1 csuser csuser 1553 Μάι 12 18:27 common.c
-rw-rw-r-- 1 csuser csuser 313 Μάι 12 17:00 common.h
-rwxrwxr-x 1 csuser csuser 12204 Μάι 12 18:25 m
-rw-rw-r-- 1 csuser csuser 2534 Μάι 12 18:00 mysh4.c
-rw-rw-r-- 1 csuser csuser 7395 Μάι 12 12:44 p3090278-mysh4.c
-rwxrwxr-x 1 csuser csuser 59 Μάι 12 17:46 that
-rwxrwxr-x 1 csuser csuser 22 Μάι 12 18:13 there
void runThat(char *cmds[][MAX_PAR], int NOP){
pid_t pid, waitPid;
int status;
int pipefd[2];
int Num_Cmds = NOP +1;
int r[Num_Cmds]; int w[Num_Cmds];
char ** cmd;
for (int i = 0; i < Num_Cmds; i++){
r[i] = -1;
w[i] = -1;
}
for (int j = 0; j < NOP; j++){
pipe(pipefd);
r[j+1] = pipefd[0];
w[j] = pipefd[1];
}
for (int i = 0; i < Num_Cmds; i++){
int h = 0;
while (cmds[i][h]!= NULL){
cmd[h] = cmds[i][h];
printf("This [%s]\n", cmd[h]);
h++;
}
cmd[h] = NULL;
printf("This [%s]\n", cmd[h]);
if (pid = fork() < 0){
perror("Fork has failed");
exit(1);
}
else if(pid == 0){
if (r[i] != -1){
close(STDIN_FILENO);
dup2(r[i],STDIN_FILENO);
}
if (w[i] != -1){
close(STDOUT_FILENO);
dup2(w[i],STDOUT_FILENO);
}
for (int j = 0; j < Num_Cmds; j++){
close(w[j]);
close(r[j]);
}
if (execvp(cmd[0], cmd)==-1){
perror("Command Failed");
exit(0);
}
}
else{
waitPid = wait(&status);
if (waitPid == -1){
perror("Waitpid failed");
exit(1);
}
close(w[i]);
if (i>0){
close(r[i]);
}
}
}
}