Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.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
C 如何在文件描述符上创建选择块_C_Linux - Fatal编程技术网

C 如何在文件描述符上创建选择块

C 如何在文件描述符上创建选择块,c,linux,C,Linux,我有一个有两个线程的进程。一个线程线程A将设置timerfd计时器,另一个线程线程B将对这些计时器执行“选择”。一旦计时器过期,线程B将向线程a指示这一点 if((wakeUpFd = shm_open("/wakeup", O_RDWR|O_CREAT|O_TRUNC, 0)) == -1) printf("Failed to open /wakeup, Errno = %d\n", errno); else { fcntl(wakeUpFd, F_SETLK, F_RDLCK);

我有一个有两个线程的进程。一个线程线程A将设置timerfd计时器,另一个线程线程B将对这些计时器执行“选择”。一旦计时器过期,线程B将向线程a指示这一点

if((wakeUpFd = shm_open("/wakeup", O_RDWR|O_CREAT|O_TRUNC, 0)) == -1)
   printf("Failed to open /wakeup, Errno = %d\n", errno);
else
{
   fcntl(wakeUpFd, F_SETLK, F_RDLCK);
}
#create a timer and add it to a list
/* wake up timer thread */
fcntl(wakeUpFd, F_SETLK, ~F_RDLCK);
if((wakeUpFd = shm_open("/wakeup", O_RDWR|O_CREAT|O_TRUNC, 0)) == -1)
   printf("Failed to open /wakeup, Errno = %d\n", errno);
else
{
   if(ftruncate(wakeUpFd, 2) == -1)
   {
      printf("Failed with ftruncate, Errno = %d\n", errno);
   }
}
#create a timer and add it to a list
/* wake up timer thread */
if(write(wakeUpFd, wakeUpStr, 1) != 1)
   printf("Failed to write to wakeUpFd\n");
要添加计时器,线程A将创建一个新的计时器,然后它将唤醒线程B,将该计时器包含在其对select的调用中。我正试图通过使用文件描述符来唤醒线程B。然后,线程B将调用该FD上的select以及调用timerfd返回的所有FD

问题是我无法创建一个我可以控制的FD,以便它在需要时导致select阻塞或返回

我曾尝试在调用fcntl时使用shm_open,并尝试在文件上使用open,但没有一个会导致select阻塞。我的所有尝试都会导致select立即返回。有没有办法创建一个会导致select阻塞的FD,直到我以某种方式更新该FD

尝试1-在shm_打开的情况下创建FD,并使用fcntl设置读取锁定:

从线程A创建FD

if((wakeUpFd = shm_open("/wakeup", O_RDWR|O_CREAT|O_TRUNC, 0)) == -1)
   printf("Failed to open /wakeup, Errno = %d\n", errno);
else
{
   fcntl(wakeUpFd, F_SETLK, F_RDLCK);
}
#create a timer and add it to a list
/* wake up timer thread */
fcntl(wakeUpFd, F_SETLK, ~F_RDLCK);
if((wakeUpFd = shm_open("/wakeup", O_RDWR|O_CREAT|O_TRUNC, 0)) == -1)
   printf("Failed to open /wakeup, Errno = %d\n", errno);
else
{
   if(ftruncate(wakeUpFd, 2) == -1)
   {
      printf("Failed with ftruncate, Errno = %d\n", errno);
   }
}
#create a timer and add it to a list
/* wake up timer thread */
if(write(wakeUpFd, wakeUpStr, 1) != 1)
   printf("Failed to write to wakeUpFd\n");
从线程A添加计时器

if((wakeUpFd = shm_open("/wakeup", O_RDWR|O_CREAT|O_TRUNC, 0)) == -1)
   printf("Failed to open /wakeup, Errno = %d\n", errno);
else
{
   fcntl(wakeUpFd, F_SETLK, F_RDLCK);
}
#create a timer and add it to a list
/* wake up timer thread */
fcntl(wakeUpFd, F_SETLK, ~F_RDLCK);
if((wakeUpFd = shm_open("/wakeup", O_RDWR|O_CREAT|O_TRUNC, 0)) == -1)
   printf("Failed to open /wakeup, Errno = %d\n", errno);
else
{
   if(ftruncate(wakeUpFd, 2) == -1)
   {
      printf("Failed with ftruncate, Errno = %d\n", errno);
   }
}
#create a timer and add it to a list
/* wake up timer thread */
if(write(wakeUpFd, wakeUpStr, 1) != 1)
   printf("Failed to write to wakeUpFd\n");
唤醒线程B

#when select returns
if(FD_ISSET(wakeUpFd, &timerSet))
{
   fcntl(wakeUpFd, F_SETLK, F_RDLCK);
}
#check all other timer FD's
#when select returns
if(FD_ISSET(wakeUpFd, &timerSet))
{
   read(wakeUpFd, wakeUpBuf, 10);
}
#check all other timer FD's
尝试2-使用shm_打开并读取/写入数据:

从线程A创建FD

if((wakeUpFd = shm_open("/wakeup", O_RDWR|O_CREAT|O_TRUNC, 0)) == -1)
   printf("Failed to open /wakeup, Errno = %d\n", errno);
else
{
   fcntl(wakeUpFd, F_SETLK, F_RDLCK);
}
#create a timer and add it to a list
/* wake up timer thread */
fcntl(wakeUpFd, F_SETLK, ~F_RDLCK);
if((wakeUpFd = shm_open("/wakeup", O_RDWR|O_CREAT|O_TRUNC, 0)) == -1)
   printf("Failed to open /wakeup, Errno = %d\n", errno);
else
{
   if(ftruncate(wakeUpFd, 2) == -1)
   {
      printf("Failed with ftruncate, Errno = %d\n", errno);
   }
}
#create a timer and add it to a list
/* wake up timer thread */
if(write(wakeUpFd, wakeUpStr, 1) != 1)
   printf("Failed to write to wakeUpFd\n");
从线程A添加计时器

if((wakeUpFd = shm_open("/wakeup", O_RDWR|O_CREAT|O_TRUNC, 0)) == -1)
   printf("Failed to open /wakeup, Errno = %d\n", errno);
else
{
   fcntl(wakeUpFd, F_SETLK, F_RDLCK);
}
#create a timer and add it to a list
/* wake up timer thread */
fcntl(wakeUpFd, F_SETLK, ~F_RDLCK);
if((wakeUpFd = shm_open("/wakeup", O_RDWR|O_CREAT|O_TRUNC, 0)) == -1)
   printf("Failed to open /wakeup, Errno = %d\n", errno);
else
{
   if(ftruncate(wakeUpFd, 2) == -1)
   {
      printf("Failed with ftruncate, Errno = %d\n", errno);
   }
}
#create a timer and add it to a list
/* wake up timer thread */
if(write(wakeUpFd, wakeUpStr, 1) != 1)
   printf("Failed to write to wakeUpFd\n");
唤醒线程B

#when select returns
if(FD_ISSET(wakeUpFd, &timerSet))
{
   fcntl(wakeUpFd, F_SETLK, F_RDLCK);
}
#check all other timer FD's
#when select returns
if(FD_ISSET(wakeUpFd, &timerSet))
{
   read(wakeUpFd, wakeUpBuf, 10);
}
#check all other timer FD's
尝试3-与尝试2基本相同,但使用open而不是shm_open

Try 4-与Try 1相同,但使用fcntl(wakeUpFd、F_SETFL、~O_NONBLOCK)而不是fcntl(wakeUpFd、F_SETLK、~F_RDLCK)

阅读规范,尤其是其中说明:

与常规文件相关联的文件描述符应始终为“准备读取”、“准备写入”和“错误”条件选择“真”


不能对常规文件的文件描述符设置
select()
块。您必须有一个管道、套接字或沿着这些线的东西,作为您选择的文件。

使用Unix域套接字对,例如用于通信。当线程A创建一个新的timerfd时,它只需将新的描述符(一个
int
)写入通信套接字
commsd[0]

当线程B注意到通信套接字
commsd[1]
可读时,它从中读取一个或多个
int
s。每个
int
显然是一个新的timerd描述符,因此线程B必须将每个描述符添加到set it
select()
s on中

在线程B中,我建议在循环中使用非阻塞读取从通信套接字读取:

    char     buffer[8 * sizeof(int)];
    size_t   head = 0, tail = 0;
    ssize_t  bytes;
    int      new_timerfd;

    while (1) {

        if (head >= tail)
            head = tail = 0;
        else
        if (head > 0) {
            memmove(buffer, buffer + head, tail - head);
            tail -= head;
            head = 0;
        }

        if (tail < sizeof buffer) {
            bytes = recv(commsd[1], buffer + head, sizeof buffer - tail, MSG_DONTWAIT);
            if (bytes > (ssize_t)0)
                head += bytes;
        }

        if (head >= tail)
            break;

        while (head + sizeof (int) <= tail) {
            /* Unaligned version of new_timerfd = *(int *)(buffer + head); */
            memmove(&new_timerfd, buffer + head, sizeof new_timerfd);
            head += sizeof (int);

            /*
             * Add new_timerfd to select()ed set
            */
        }
    }
char缓冲区[8*sizeof(int)];
头部尺寸=0,尾部尺寸=0;
ssize_t字节;
int new_timerfd;
而(1){
如果(头部>=尾部)
头=尾=0;
其他的
如果(头>0){
memmove(缓冲器、缓冲器+头部、尾部-头部);
尾-=头;
水头=0;
}
if(尾部<缓冲区大小){
bytes=recv(commsd[1],buffer+head,buffer-tail的大小,MSG_DONTWAIT);
如果(字节数>0)
头+=字节;
}
如果(头部>=尾部)
打破

while(head+sizeof(int)欢迎来到Stack Overflow。请尽快阅读。您在这里做得很好,解释了您尝试的内容,并且在询问之前明确尝试了相当数量。做得好。感谢您的回答,它非常彻底。在我的情况下,我通过内存处理通信。FD只是用来唤醒计时器处理程序。一个管道对我来说这是最快的方法。