使用select()的子操作在execvp()

时间:2017-12-04 04:35:15

标签: c select fork

运行此代码片段以试验管道和信号。我试图学习如何在管道之间正确使用select()函数。

这个过程会分叉。如果有从stdIn读取的内容,则将其写入管道的写入端。它应该执行通过终端输入的基本命令,或者在代码中运行硬编码命令。 (它现在正在运行硬代码,因为" ls。")

当我运行此片段时,当我按下字母时,它应该退出并完全停止运行" q"然后是ENTER,或者它应该在运行其分配的进程后退出。

相反,即使在我点击" q"或者运行它不会完全停止程序的过程。它仍在等待输入。一旦我按下ENTER,它停止运行,但它甚至从未执行我的进程。

例如,如果我编译并运行它作为" ./ test ls"或者甚至只是运行" ./ test" (因为ls是硬编码的,所以我应该只运行),它不会运行命令ls。程序将继续运行,直到我再次点击ENTER。

我确定我对select()的基本理解与此问题有关。我很确定我的select()语句需要在某些时候中断,但我不知道检查这个的内容或方法。

我被告知有一种方法WIFEXITED()可以帮助我,但我不确定它在这种情况下是如何应用的。

我也想知道如何检查你的管道是否空了!

我知道我希望这能够从终端获取输入并记录它并运行内置函数。

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <stdio.h>

int main() {
  int in[2]; // parent writes; child reads
  pipe(in);
  if (fork() == 0) {
    // instantiate the values that will be execed
    char *a[2];
    //a[0] = "./test3";
    a[0] = "ls";
    a[1] = NULL;

    // redirects what is being read from stdin to the pipe
    //this redirection is for a separate test that is not included
    close(in[1]);
    close(0);
    dup(in[0]);

    close(in[0]); // close read
    execvp(a[0], a);
  }
  else {
    close(in[0]); // only want parent to write

    // select() params
    int nfds = 3;
    int check = -1;
    int done = 0;
    fd_set readfds;
    fd_set writefds;

    FD_ZERO(&readfds); // set select params
    FD_SET(0, &readfds);
    FD_SET(in[1], &writefds);

    while ((check = select(nfds, &readfds, &writefds, NULL, NULL)) > 0) {
      int size = 0;
      char buf[1000];

      // write to pipe for child
      if (FD_ISSET(0, &readfds) && FD_ISSET(in[1], &writefds)) {
        while ((size = read(0, buf, sizeof(buf))) != 0) {

          write(in[1], buf, size);
        }
      }
      // reset
      FD_ZERO(&readfds);
      FD_SET(0, &readfds);
      FD_SET(in[1], &writefds);
    }
    printf("%d --------------- %d\n", (FD_ISSET(in[1], &writefds)),
           FD_ISSET(0, &readfds));
  }
  return 0;
}

如果取消注释[0] = ./test并且评论了[0] = ls,则可以使用上面的剪辑运行测试代码的潜在集合。

#include <sys/time.h>
#include <sys/types.h> 
#include <unistd.h>
#include <stdio.h>
#include <string.h>

#include <sys/select.h>

int main () {

    int fd;
    char buf[11];
    int ret, sret;
    int flag = 0;
    fd = 0;

    fd_set readfds;
    struct timeval timeout;


    while(1) {

        FD_ZERO(&readfds);
        FD_SET(fd, &readfds);

        timeout.tv_sec = 5;
        timeout.tv_usec = 0;

        sret = select(fd + 1, &readfds, NULL, NULL, NULL);

            memset((void *) buf, 0, 11);
            ret = read(fd, (void *) buf, 10);
            flag = strcmp(buf, "q\n") == 0;

            if (flag) {
                return 0;
            }
            printf("ret = %d\n", ret);

            if(ret != -1) {
                printf(" buf = %s\n", buf);
            }

    }
    return 0;
}

0 个答案:

没有答案