1

我正在尝试做一些初学者内核模块/用户级程序通信。我之前得到了使用fdopen()效果很好的建议,但我发现我需要使用open(),read()write()不是。我阅读了这些手册页,并认为我将 fopen、fgets、fputs 正确转换为这些,并且我的程序可以编译,但我没有得到所需的输出。

我有一个计时器,如果我输入./userprogram -s (int) (name)eg ./userprogram -s 5 hello,5 秒后它将hello通过与我的内核模块通信打印到控制台。在我切换到这些新功能后,它改为打印/lib/ld-uClibc.so.0(现在似乎要等待约 5 秒)。我是否还需要更改内核级代码的工作方式?我以为我只是能够更改用户级程序,内核模块将继续像以前一样工作。这是我尝试使用注释掉的原始代码:

// open file
int pFile;
pFile = open("/dev/mytimer", O_RDWR);
if (pFile < 0) {
    fprintf (stderr, "mytimer module isn't loaded\n");
    return 1;
}

// Check if timer set
if (argc >= 4 && strcmp(argv[1], "-s") == 0) {
    lenNum = strlen(argv[2]);
    lenName = strlen(argv[3]);
    char *ptr = malloc(lenNum+lenName+4);
    strncat(ptr, argv[1], 2);//flag
    strncat(ptr," ", 1);
    strncat(ptr, argv[2], lenNum);//timer length
    strncat(ptr," ", 1);
    strncat(ptr, argv[3], lenName);//message

    /* fputs(ptr, pFile); */
    write(pFile, ptr, sizeof(ptr));
    /*
    while (fgets(line, 256, pFile) != NULL) {
        printf("%s", line);
    } */
    while (read(pFile, ptr, sizeof(ptr)) != 0) {
        printf("%s", line);
    }   

任何建议表示赞赏。

4

2 回答 2

4

[我] 以为我正确地将 fopen、fgets、fputs 转换为这些

……但你错了。没有基于单行write()的等价于fputs(),也没有基于单行read()的等价于fgets()。基于流的 I/O 函数做了很多你在使用低级read()s 和write()s 时必须自己完成的工作。

其中一些差异是:

  • read()不提供字符串终止。你必须自己做。
  • write()不注意字符串终止。如果您希望它在字符串终止符处停止,那么您必须通过您要求它传输的字节数来控制它。
  • read()并且write()两者都不能保证在一次调用中传输请求的全部字节数。如果要传输特定数量的字节,则必须准备循环。
  • read()不会在任何特定字符处自动停止,包括换行符
  • 大多数流都提供缓冲,对您来说是不可见的。如果你想缓冲你read()的 s 和write()s 那么你必须自己处理它(但这些函数非常适合它)。

但是,在您的特定情况下,您还犯了语义错误。write()和的第三个参数read()是要传输的最大字节数——通常是缓冲区的大小——但sizeof(ptr)它是指针本身的大小,而不是它指向的空间大小。

于 2016-03-18T21:45:17.943 回答
3

sizeof(ptr)可能是 4 或 8(即sizeof(char *)),而不是您要写入的数据的长度。

而且构建数据的方式非常繁琐。为什么不使用单个sprintf(), 或者,如果有的话,asprintf(),它甚至可以分配内存:

char *ptr;
int i;

i = asprintf (&ptr, "%s %s %s", argv[1], argv[2], argv[3]);
write (pFile, ptr, i);
free(ptr);

是不是又甜又简洁?

于 2016-03-18T21:41:13.057 回答