Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Linux epoll系统调用,尽管数据可用,但仍在等待_Python_C_Linux_System Calls_Epoll - Fatal编程技术网

Python Linux epoll系统调用,尽管数据可用,但仍在等待

Python Linux epoll系统调用,尽管数据可用,但仍在等待,python,c,linux,system-calls,epoll,Python,C,Linux,System Calls,Epoll,使用简单的父子程序测试Linux syscallepoll 预期行为 当孩子们每秒写一个“否”时,家长们应该从管道中读取它,然后每秒向标准输出一个“否” 实际行为 父级等待,直到子级写入所有no,然后从管道读取所有数据并写入stdout。通过对父对象执行strace来验证。它在epoll_等待中阻塞 家长 #define _GNU_SOURCE #include <stdio.h> #include <unistd.h> #include <stdlib.h>

使用简单的父子程序测试Linux syscallepoll

预期行为

当孩子们每秒写一个“否”时,家长们应该从管道中读取它,然后每秒向标准输出一个“否”

实际行为

父级等待,直到子级写入所有no,然后从管道读取所有数据并写入stdout。通过对父对象执行strace来验证。它在epoll_等待中阻塞

家长

#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <error.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/epoll.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define NAMED_FIFO "aFifo"

static void set_nonblocking(int fd) {
  int flags = fcntl(fd, F_GETFL, 0);
  if (flags == -1) {
    perror("fcntl()");
    return;
  }
  if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
    perror("fcntl()");
  }
}

void errExit(char *msg) {
  perror(msg);
  exit(-1);
}

void printArgs(char **argv,char **env) {
  for(int i=0;argv[i];i++)
    printf("argv[%d]=%s\n",i,argv[i]);

  for(int i=0;env[i];i++)
    printf("env[%d]=%s\n",i,env[i]);
}

void PrintNos(short int max,char *name) {
  int fifo_fd,rVal;
  int bSize=2;
  char buffer[bSize];

  fifo_fd = open(NAMED_FIFO,O_RDONLY);
  if(fifo_fd<0)
    errExit("open");

  for(short int i=0;i<max;i++) {
    rVal = read(fifo_fd,buffer,bSize);
    if(rVal != bSize)
      errExit("read");
    printf("%03d\n",i);
  }
}

int main(int argc, char *argv[],char *env[]) {
  //int pipe_fds_child_stdin[2] ;
  int pipe_fds_child_stdout[2] ;
  pid_t child_id ;

  //if( pipe(pipe_fds_child_stdin) < 0 )
  //  errExit("pipe");

  if( pipe(pipe_fds_child_stdout) < 0 )
    errExit("pipe");

  child_id = fork();

  if( child_id > 0 ) {
    const int MAX_POLL_FDS = 2;
    const int BUF_SIZE = 4;

    size_t readSize;
    char buf[BUF_SIZE];
    int status;

    int epoll_fd;
    int nfds ;
    struct epoll_event e_e, e_events[MAX_POLL_FDS];

    memset(e_events,'\0',sizeof(e_events));
    memset(&e_e,'\0',sizeof(e_e));
    //close(pipe_fds_child_stdin[0]);
    close(pipe_fds_child_stdout[1]);

    epoll_fd = epoll_create1(0);
    if(epoll_fd < 0)
      errExit("epoll_create1");

    e_e.data.fd = pipe_fds_child_stdout[0];
    e_e.events  = EPOLLIN;

    if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, pipe_fds_child_stdout[0], &e_e) < 0)
      errExit("epoll_ctl");

    while(1) {
      nfds = epoll_wait(epoll_fd, e_events,MAX_POLL_FDS,-1);
      if( nfds < 0)
        errExit("epoll_wait");

      for(int i=0;i<nfds;i++) {
        if( e_events[i].data.fd == pipe_fds_child_stdout[0]) {
          if( e_events[i].events & EPOLLIN) {
            readSize = read(pipe_fds_child_stdout[0],buf,BUF_SIZE);
            if( readSize == BUF_SIZE ) {
              write(STDOUT_FILENO,buf,BUF_SIZE);
            } else if(readSize == 0) { // eof
              errExit("readSize=0");
            } else {
              errExit("read");
            }
          } else if( e_events[i].events & EPOLLHUP) {
            printf("got EPOLLHUP on pipefd\n");
            wait(&status);
            exit(0);
          } else {
            errExit("Unexpected event flag returned by epoll_wait on waited fd");
          }
        } else  {
          errExit("epoll_wait returned non-awaited fd");
        }
      }
    }
  } else if( child_id == 0 ) {
    close(0);
    close(1);
    //close(pipe_fds_child_stdin[1]);
    close(pipe_fds_child_stdout[0]);

    //dup2(pipe_fds_child_stdin[0],0);
    dup2(pipe_fds_child_stdout[1],1);

    execvpe(argv[1],&(argv[1]),env);
    //PrintNos(100,"P");
    //errExit("execvp");
  } else {
    errExit("fork");
  }
}

这是由于python缓冲,可以通过将-u选项传递给python来禁用缓冲


经过大量的搜索和研究,了解到这是由于管道缓冲。虽然客户端写入,但它在管道缓冲区中。只有在管道缓冲区已满后,内核才会在该描述符上发送就绪事件。最小值是pagesize,内核不允许设置为低于该值。但它可以增加。通过将epoll更改为poll/select,实现了这一点。更改为轮询/选择后,行为相同。虽然数据在管道中可用,但仍处于阻塞状态

import fcntl
import os

F_SETPIPE_SZ=1031
fds = os.pipe()
for i in range(5):
    print(fcntl.fcntl(fds[0],F_SETPIPE_SZ,64))


$ python3.7 pipePageSize.py 
4096
4096
这是修改后的客户端。在服务器中进行适当的更改

import time

pageSize=1024*8

for x in range(100):
    time.sleep(0.5)
    print(f'{x:-{pageSize}d}')

这是由于python缓冲,可以通过将-u选项传递给python来禁用缓冲


经过大量的搜索和研究,了解到这是由于管道缓冲。虽然客户端写入,但它在管道缓冲区中。只有在管道缓冲区已满后,内核才会在该描述符上发送就绪事件。最小值是pagesize,内核不允许设置为低于该值。但它可以增加。通过将epoll更改为poll/select,实现了这一点。更改为轮询/选择后,行为相同。虽然数据在管道中可用,但仍处于阻塞状态

import fcntl
import os

F_SETPIPE_SZ=1031
fds = os.pipe()
for i in range(5):
    print(fcntl.fcntl(fds[0],F_SETPIPE_SZ,64))


$ python3.7 pipePageSize.py 
4096
4096
这是修改后的客户端。在服务器中进行适当的更改

import time

pageSize=1024*8

for x in range(100):
    time.sleep(0.5)
    print(f'{x:-{pageSize}d}')

您似乎已删除此问题的早期实例,并创建了一个新实例。那没用。相反,你应该问一个具体的问题。到目前为止,还没有一个美元。所以提供了删除一个问题的条款,我这样做了,并发布了一个新问题。我不知道这是怎么回事。您看到这篇文章的事实验证了我的推理。因此还提供了一个函数来编辑一个问题,这是最好的方法。
epoll()
不是从管道读取的好选择,因为只有在管道的写入端关闭时才有响应。@user3629249 thx。请提供支持您的主张的文档。您似乎已删除此问题的早期实例,并创建了一个新实例。那没用。相反,你应该问一个具体的问题。到目前为止,还没有一个美元。所以提供了删除一个问题的条款,我这样做了,并发布了一个新问题。我不知道这是怎么回事。您看到这篇文章的事实验证了我的推理。因此还提供了一个函数来编辑一个问题,这是最好的方法。
epoll()
不是从管道读取的好选择,因为只有在管道的写入端关闭时才有响应。@user3629249 thx。如果您的理解不正确,请提供支持您索赔的文件。问题在于应用程序级缓冲,而不是任何内核限制。您需要刷新Python流,而不是增加写入的数据量。后者将是对电子的疯狂浪费。@n.m.不想说,但你是对的!python-u修复了这个问题。您的理解是错误的。问题在于应用程序级缓冲,而不是任何内核限制。您需要刷新Python流,而不是增加写入的数据量。后者将是对电子的疯狂浪费。@n.m.不想说,但你是对的!python-u修复了这个问题。