c - 程序在 FD_SET 宏 (select()) 中挂起

标签 c linux select

我的程序有问题,我不知道这个问题的根源是什么。我的程序是从多个 RFID 阅读器(最多 8 个阅读器)读取数据,所以我使用 select() 来确定是否有数据要读取。这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>
#include <termios.h>
#include <signal.h>

#define KNRM  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"

int main(int argc, char *argv[]) {
    // Variables and constants
    int fd[8];
    int max_fd;
    char *devices[8];
    char name[256] = "Unknown";
    fd_set readset;

    printf("\n");

// 1. Setup check
    // 1.1 Check if user is root
    if ((getuid()) != 0) {
        printf(KRED "Warning: " KNRM "You are not root! This may not work.\n");
    }

    // 1.2 Check that all of the argument vectors has data (within the argument count)
    for(int i = 1; i < argc; i++){
        if (argv[i] == NULL) {
            printf(KRED "Error: " KNRM "Something is wrong with the path to the device event\n");
            exit(0);
        }
    }

    // 1.3 Copy the vectors to device array
    for(int i = 1; i < argc; i++){
        devices[i] = argv[i];
    }


// 2. Open Devices
    for(int i = 1; i < argc; i++){
        if ((fd[i] = open(devices[i], O_RDONLY)) == -1){
            printf(KRED "Warning: " KNRM "%s is not a valid device.\n", devices[i]);
        }
    }


// 3. Print Device Names
    printf("\n----------------------------------------------------------------------------\n");
    for(int i = 1; i < argc; i++){
        // Check if device open was successful
        if(fd[i] != -1){
            ioctl(fd[i], EVIOCGNAME(sizeof(name)), name);
            printf(" Reading From : %s (%s)\n", devices[i], name);
        }
    }
    printf("----------------------------------------------------------------------------\n");
    printf("\n");

    // 3.1 Initialize set
    FD_ZERO(&readset);
    max_fd = 0;
    for(int j = 0; j < argc; j++){
        printf(KGRN "now here" KNRM "\n");
        FD_SET(fd[j], &readset);        // <-- Stalls here!!
        printf("not here\n");
        max_fd = (max_fd > fd[j]) ? max_fd : fd[j];
        printf("%i\n", max_fd);
    }

// 4. Now, check for readability
    int result = select(max_fd+1, &readset, NULL, NULL, NULL);
    if (result == -1) {
       printf(KRED "Warning: " KNRM "Some error occurred while checking for readability\n\n");
    } else {
        for (int i = 0; i < argc; i++) {
            if (FD_ISSET(fd[i], &readset)) {
                printf("%u is readable\n", fd[i]);
          }
       }
    }

    return 0;
}

它卡在这一行(当第 4 点被注释时,如果第 4 点没有被注释,程序将在同一行退出):

FD_SET(fd[j], &readset);        // <-- Stalls here!!

我不知道哪里出了问题,所以欢迎任何建议! (下面是显示正在运行的程序的屏幕截图)

Example compiling and running the program

最佳答案

您程序中数组的索引不一致,给您 undefined behavior当您访问未初始化的索引 0 时。

您也不检查未打开的文件描述符,并盲目地尝试在 fd 中设置和使用所有内容。

关于c - 程序在 FD_SET 宏 (select()) 中挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25278847/

相关文章:

javascript - 根据在下拉列表中选择的值动态更改日期选择器

c - C 中的 FreeBSD SysCall -> 函数的隐式声明 'modfind'

linux - 为文件夹中的文件创建新的符号链接(symbolic link)

c - 如何在 C 中的 char 数组末尾添加一个 char(零)?

linux - 使用 shell 脚本从控制台添加多个值

php - 从网站杀死一个进程

MySQL 从 2 个表中选择不同值并进行计数

sql - Oracle Date数据类型,通过SQL转换为 'YYYY-MM-DD HH24:MI:SS TMZ'

objective-c : Accessing variadic arguments in method

c - 使用 GDB 更改 for 循环条件?