gpt4 book ai didi

c - 管道和 select() 有问题

转载 作者:太空宇宙 更新时间:2023-11-04 04:09:01 25 4
gpt4 key购买 nike

我似乎在使用 pipe 和 select 时遇到了问题。

上下文:必须编写一些将由 shell 执行的程序:
logn [--tick n] cmd [args] [, cmd [args]]...

基本上,它是一个同时运行多个程序的程序。

约束:每个输出行必须以其前面的命令编号开头,格式为 printf "%d: %s"
即:

0: first line of first command.  
0: second line of first command.
1: first line of second command.
0: third line of first command.
1: second line of second command.

如果指定了tick,如果n秒内没有输出,系统将打印一个句号。必须使用 select()如果最后输出的是一个句点,系统不会打印另一个句点。

问题:

  1. 第二个命令的输出似乎转到了第一个管道的 p[0]。
    当我读入 p[0][0] 时,我得到了发送给 p[1][0] 的内容。 p[1][0]里好像什么都没有。

  2. 每当我的选择遇到超时,它似乎就卡在那里。

我之前问过一个问题,所以看起来很熟悉。由于问题不同,我发了一个新帖子。旧帖子对我弄清楚 fork 有很大帮助。

这是我的代码:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include "readline.h"

/* Fetches the number of commands in parameters. Number of Commas + 1 */
int getNbCmd(char ** argv)
{
int nbCmd = 1;
int i = 0;
while(argv[i] != '\0')
{
if(strcmp(argv[i], ",") == 0)
nbCmd++;
i++;
}
return nbCmd;
}


/* Fills the Command Array */
void getCommandes(char *** tbCmd, int argc, char ** argv)
{
int indexArgv = 1;
int indexCmd = 0;
int indexTbCmd = 0;

char ** cmd = (char **)malloc(argc*sizeof(char *));
if(indexArgv < argc)
{
if(strcmp(argv[indexArgv], "--tick") == 0)
indexArgv = 3;
}

while (indexArgv < argc)
{
if(strcmp(argv[indexArgv], ",") == 0)
{
cmd[indexCmd] = (char *) 0;
tbCmd[indexTbCmd] = cmd;
free(cmd);
cmd = (char **)malloc(argc*sizeof(char *));

indexTbCmd++;
indexCmd = 0;
}
else
{
char * arg;
arg = argv[indexArgv];
cmd[indexCmd] = arg;

indexCmd++;
}
indexArgv++;
}

cmd[indexCmd] = (char *) 0;
tbCmd[indexTbCmd] = cmd;
free(cmd);
}

int main (int argc, char ** argv)
{
int nbCmds = getNbCmd(argv);
int tick = -1;

char *** tbCmd = (char ***) malloc (nbCmds*sizeof(char **));

if(argc > 3)
{
if(strcmp(argv[1], "--tick") == 0)
tick = atoi(argv[2]);
}

getCommandes(tbCmd, argc, argv);

int i,j;

pid_t pidM[nbCmds];
int p[nbCmds][2];

for (i = 0;i < nbCmds;i++)
{
if ( pipe( p[i] ) != 0 ){ perror( "pipe()" ); exit(1); }
}

for (i = 0;i < nbCmds;i++)
{
// fork() to get child process
pidM[i] = fork();

if ( pidM[i] < 0 ){ perror( "fork()" ); exit(1); }
//Child Processing
else if (pidM[i] == 0)
{
close(p[i][0]);
dup2(p[i][1], STDOUT_FILENO);

int ret;
ret = execvp(tbCmd[i][0], tbCmd[i]);
perror("execvp()");
}
}

// Parent Processing
for (i = 0;i < nbCmds;i++)
{
close(p[i][1]);
}

char * buffer;
int retval = 1;
int boolAfficher = 0;
int nbNull = 0;

fd_set set;
struct timeval timeout;

/* Initialize the file descriptor set. */
FD_ZERO (&set);
for (i = 0;i < nbCmds;i++)
{
FD_SET (p[i][0], &set);
}

while(nbNull < nbCmds)
{
if(tick >= 0)
{
timeout.tv_sec = (unsigned int)tick;
timeout.tv_usec = 0;
retval = select (FD_SETSIZE,&set, NULL, NULL, &timeout);
}
else
retval = select (FD_SETSIZE,&set, NULL, NULL, NULL);

if(retval == 0)
{
if(boolAfficher == 0 && tick >= 0)
{
printf(".\n");
boolAfficher = 1;
}
}
else if(retval > 0)
{
for (i = 0;i < nbCmds;i++)
{
if(FD_ISSET(p[i][0], &set))
{
buffer = readline(p[i][0]);
if(buffer[0] != '\0')
{
printf("%d: %s", i, buffer);
}
else
{
FD_CLR(p[i][0], &set);
nbNull++;
}
}
else
printf("Not ISSET[%d]\n", i);

free(buffer);
}
}
else
perror("select()");
}

wait(NULL);
free(tbCmd);
exit(0);
}

最佳答案

我想通了!

当递归调用 logn 时仍然有错误

即:./logn --tick 2 ./logn --tick 2 ./cmd1 0 un 6 deux , ./logn --tick 2 ./cmd1 1 trois 6 quatre

./cmd1 的代码

while test "x$#" != "x0"; do
sleep $1
shift
test "x$#" != "x0" || exit
echo $1
shift
done

如果有人感兴趣,这是我的固定代码:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include "readline.h"

/* Fetches the number of commands in parameters. Number of Commas + 1 */
int getNbCmd(char ** argv)
{
int nbCmd = 1;
int i = 0;
while(argv[i] != '\0')
{
if(strcmp(argv[i], ",") == 0)
nbCmd++;
i++;
}

return nbCmd;
}


/* Fills the Command Array */
void getCommandes(char *** tbCmd, int argc, char ** argv)
{
int indexArgv = 1;
int indexCmd = 0;
int indexTbCmd = 0;

char ** cmd = (char **)malloc(argc*sizeof(char *));
if(indexArgv < argc)
{
if(strcmp(argv[indexArgv], "--tick") == 0)
indexArgv = 3;
}

while (argv[indexArgv] != '\0')
{
if(strcmp(argv[indexArgv], ",") == 0)
{

cmd[indexCmd] = (char *) 0;
tbCmd[indexTbCmd] = cmd;
cmd = (char **)malloc(argc*sizeof(char *));

indexTbCmd++;
indexCmd = 0;
}
else
{

char * arg;
arg = argv[indexArgv];
cmd[indexCmd] = arg;

indexCmd++;
}
indexArgv++;
}


cmd[indexCmd] = (char *) 0;
tbCmd[indexTbCmd] = cmd;
free(cmd);
}


int main (int argc, char ** argv)
{
int nbCmds = getNbCmd(argv);

int tick = -1;

char *** tbCmd = (char ***) malloc (nbCmds*sizeof(char **));

if(argc > 3)
{
if(strcmp(argv[1], "--tick") == 0)
tick = atoi(argv[2]);
}

getCommandes(tbCmd, argc, argv);

int i,j;

pid_t pidM[nbCmds];
int p[nbCmds][2];

for (i = 0;i < nbCmds;i++)
{
if ( pipe( p[i] ) != 0 ){ perror( "pipe()" ); exit(1); }
}

for (i = 0;i < nbCmds;i++)
{
// fork() to get child process
pidM[i] = fork();

if ( pidM[i] < 0 ){ perror( "fork()" ); exit(1); }
//Child Processing
else if (pidM[i] == 0)
{
close(p[i][0]);
dup2(p[i][1], STDOUT_FILENO);
int ret;

ret = execvp(tbCmd[i][0], tbCmd[i]);
perror("execvp()");
_exit(1);
}
}

// Parent Processing

for (i = 0;i < nbCmds;i++)
{
close(p[i][1]);
}

char * buffer = NULL;
int retval = 1;
int boolAfficher = 0;

int nbNull = 0;
int isOk[nbCmds];

for (i = 0;i < nbCmds;i++)
{
isOk[i] = 1;
}

fd_set set;
struct timeval timeout;

while(nbNull < nbCmds)
{
FD_ZERO (&set);
for (i = 0;i < nbCmds;i++)
{
if(isOk[i] == 1)
FD_SET (p[i][0], &set);
}

if(tick > 0)
{
timeout.tv_sec = (unsigned int)tick;
timeout.tv_usec = 0;
retval = select (FD_SETSIZE,&set, NULL, NULL, &timeout);
}
else
{
timeout.tv_sec = 0;
timeout.tv_usec = 0;
retval = select (FD_SETSIZE,&set, NULL, NULL, &timeout);
}

if(retval == 0)
{
if(boolAfficher == 0 && tick >= 0)
{
printf(".\n");
boolAfficher = 1;
}
}
else
{
for (i = 0;i < nbCmds;i++)
{
if(FD_ISSET(p[i][0], &set))
{
buffer = readline(p[i][0]);
if(buffer[0] != '\0')
{
printf("%d: %s", i, buffer);
boolAfficher = 0;
}
else
{
isOk[i] = 0;
nbNull++;
}
free(buffer);
}
}
}
}

wait(NULL);
free(tbCmd);
exit(0);
}

关于c - 管道和 select() 有问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1856624/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com