在C中实现多个管道时遇到问题
我试图用C实现一些Shell命令,但是管道给我带来了一些麻烦(我把大部分代码都踢出去了,所以你们可以编译它——如果需要的话) 我和他2011年发布的Mkabs解决方案非常接近 在经历了它之后,我以为我已经把它放下了,但它不起作用 简单示例:>>**ls | sort-r**在C中实现多个管道时遇到问题,c,shell,unix,C,Shell,Unix,我试图用C实现一些Shell命令,但是管道给我带来了一些麻烦(我把大部分代码都踢出去了,所以你们可以编译它——如果需要的话) 我和他2011年发布的Mkabs解决方案非常接近 在经历了它之后,我以为我已经把它放下了,但它不起作用 简单示例:>>**ls | sort-r** 第一个子级使用第一个管道作为标准输出{1} 第二个子级使用第一个管道[0]作为stdin{0} 但两个exec()都失败,原因是:enoint,没有这样的文件或目录 无论我是从userInput读取命令还是从给定字符串硬
- 第一个子级使用第一个管道作为标准输出{1}
- 第二个子级使用第一个管道[0]作为stdin{0}
无论我是从userInput读取命令还是从给定字符串硬编码读取命令,它都会失败 因此,错误必须在executepe()fkt中,无需遍历其余部分
#define _POSIX_C_SOURCE 1
#include <alloca.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/times.h>
#include <sys/wait.h>
typedef char* string;
static int keepRunning = 1;
char inputBuffer[512];
string satz[256];
int j,comCount, modePipe,mode;
void Tokens(string);
void ExecutePipe(void);
int ScanInput(void);
void Tokens(string token){
int len;
char* ptrC;
j=0;
satz[j] = strtok (inputBuffer, token);
while (satz[j] != NULL)
{
j++;
satz[j] = strtok (NULL, token);
}
comCount =j;
/*REPLACE NEWLINE of LAST COMMAND */
len =strlen(satz[j-1]);
ptrC = satz[j-1];
for (j=0;j<len;j++){
if (*ptrC == '\n'){
*ptrC = '\0';
}
ptrC++;
}
}
void ExecutePipe(void){
int* ptrPipe;
int i,k=0, numPipes;
pid_t pid, status;
int stdin_dupfd,stdout_dupfd;
string* ptrSatz = satz;
modePipe=1;
Tokens("|");
stdin_dupfd = dup(0);
stdout_dupfd = dup(1);
numPipes = comCount-1;
ptrPipe = (int*) alloca(numPipes*2);
for(i = 0; i < numPipes; i++){
if(pipe(ptrPipe + i*2) < 0) {
printf("Error: pipe(%d)\n",i);
return;
}
}
while(k<comCount) {
pid = fork();
if(pid < 0){
fprintf(stderr,"Error: PID.%d\n", pid);
exit(9);
}
else if(pid == 0) { /* child gets input from the previous command*/
if(k > 0){ /*if not first command*/
if(dup2(ptrPipe[(k-1) * 2], 1) < 0){ /*ptr[0]. ptr[2], ptr[4], ...*/
fprintf(stderr,"Error: dup2(firstCommand)\n");
exit(10);
}
else fprintf(stderr,"k[%d]:dupe2([%d], 0)\n",k,(k-1)*2);
}
if(k != (comCount-1) ){ /*if not last command*/
if(dup2(ptrPipe[k * 2 + 1], 1) < 0){ /*ptr[1]. ptr[3], ptr[5], ...*/
fprintf(stderr,"Error: dup2(notLastCommand)\n");
exit(11);
}
else fprintf(stderr,"k[%d]:dupe2([%d], 1)\n",k,k*2+1);
}
for(i = 0; i < 2*numPipes; i++){
close(ptrPipe[i]);
}
if( execlp(*ptrSatz, *ptrSatz) < 0 ){ /* */
fprintf(stderr,"Error: ");
fprintf(stderr,"exec(%s)(%d)\n", *ptrSatz, errno);
exit(12);
}
}
fprintf(stderr,"[%d]: %s\n", k,*ptrSatz);
ptrSatz++;
k++;
}
for(i = 0; i < 2 * numPipes; i++){
close(ptrPipe[i]);
/*printf("loop %d of %d\n ",i, 2*numPipes);*/
}
for(i = 0; i < numPipes + 1; i++){
wait(&status);
}
dup2(stdin_dupfd, 0);
dup2(stdout_dupfd, 1);
close(stdin_dupfd);
close(stdout_dupfd);
inputBuffer[0] = '\0';
modePipe=0;
}
int main (void)
{
while (keepRunning){
printf(">> ");
fgets(inputBuffer, 512, stdin); /* input buffer, max.Input(char), whereFrom?*/
mode = ScanInput(); /*checks inputBuffer on keywords, returns int 1-13*/
/*printf(">> mode:%d\n", mode);*/
switch(mode){
case 11 :
ExecutePipe();
break;
}
}
return 0;
}
int ScanInput(void){
char * pch;
pch = strstr (inputBuffer," | ");
if (pch != NULL)
return 11;
else
return 1;
}
\define\u POSIX\u C\u源代码1
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
typedef char*字符串;
静态整型修剪=1;
字符输入缓冲区[512];
字符串satz[256];
int j,comCount,MODEPPIPE,mode;
无效令牌(字符串);
无效执行实体(void);
int扫描输入(void);
无效令牌(字符串令牌){
内伦;
char*ptrC;
j=0;
satz[j]=strtok(输入缓冲区,令牌);
while(satz[j]!=NULL)
{
j++;
satz[j]=strtok(空,令牌);
}
comCount=j;
/*替换最后一个命令的换行符*/
len=strlen(satz[j-1]);
ptrC=satz[j-1];
for(j=0;jexec
只能调用一个二进制文件。您在这里给出了一个shell命令。使用system()
函数,您也可以调用shell命令,但它只能工作,因为它调用bash
来解释它
最简单的解决方案是通过系统
调用此行,然后退出
-ing,如
exec("complex|shell|command >&3");
需要改成
system("complex|shell|command >&3");
exit(0);
我的dup2迭代变量出错。
预期的行为是:
dup2 - notLast notFirst
1,1 [first]
3,1 0,0
5,1 2,0
7,1 4,0
.. ..
最后一部分错误地增加了
修复此问题后,它平稳运行每个子级仅调用单个二进制+参数。[1]exec(ls)[2]exec(sort-r)。