我对 read() 和 write() 做错了什么?
What am I doing wrong with read() and write()?
我正在尝试做一些初学者内核 module/user 级别的程序通信。我之前得到的建议是使用 fdopen()
,效果很好,但我发现我需要改用 open()
、read()
和 write()
。我阅读了这些的手册页并认为我将 fopen、fgets、fputs 正确地转换为这些并且我的程序编译,但我没有得到所需的输出。
我有一个计时器,如果我输入 ./userprogram -s (int) (name)
例如./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);
}
如有任何建议,我们将不胜感激。
sizeof(ptr)
大概是4或者8(即sizeof(char *)
),不是你要写的数据的长度。
而且你构建数据的方式极其繁琐。为什么不使用单个 sprintf()
,或者,如果你有 asprintf()
,它甚至 mallocs 内存:
char *ptr;
int i;
i = asprintf (&ptr, "%s %s %s", argv[1], argv[2], argv[3]);
write (pFile, ptr, i);
free(ptr);
是不是甜美简洁?
[I] thought I converted the fopen,fgets,fputs to these correctly
...但你错了。没有基于 write()
的单行等价于 fputs()
,也没有基于单行 read()
的等价于 fgets()
。基于流的 I/O 函数做了很多你在使用低级 read()
s 和 write()
s 时必须自己做的工作。
一些差异是:
read()
不提供字符串终止。你必须自己做。
write()
不注意字符串终止。如果你想让它在字符串终止符处停止,那么你必须通过你要求它传输的字节数来控制它。
read()
和 write()
都不能保证在一次调用中传输请求的全部字节数。如果你想传输特定数量的字节,那么你必须准备好循环。
read()
不会在任何特定字符处自动停止,包括换行符
- 大多数流都提供缓冲,对您来说是不可见的。如果你想缓冲你的
read()
s 和 write()
s 那么你必须自己处理它(但那些功能非常适合它)。
但是,在您的特定情况下,您也犯了语义错误。 write()
和 read()
的第三个参数是要传输的最大字节数——通常是缓冲区的大小——但 sizeof(ptr)
是指针本身的大小,而不是它指向的 space 的大小。
我正在尝试做一些初学者内核 module/user 级别的程序通信。我之前得到的建议是使用 fdopen()
,效果很好,但我发现我需要改用 open()
、read()
和 write()
。我阅读了这些的手册页并认为我将 fopen、fgets、fputs 正确地转换为这些并且我的程序编译,但我没有得到所需的输出。
我有一个计时器,如果我输入 ./userprogram -s (int) (name)
例如./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);
}
如有任何建议,我们将不胜感激。
sizeof(ptr)
大概是4或者8(即sizeof(char *)
),不是你要写的数据的长度。
而且你构建数据的方式极其繁琐。为什么不使用单个 sprintf()
,或者,如果你有 asprintf()
,它甚至 mallocs 内存:
char *ptr;
int i;
i = asprintf (&ptr, "%s %s %s", argv[1], argv[2], argv[3]);
write (pFile, ptr, i);
free(ptr);
是不是甜美简洁?
[I] thought I converted the fopen,fgets,fputs to these correctly
...但你错了。没有基于 write()
的单行等价于 fputs()
,也没有基于单行 read()
的等价于 fgets()
。基于流的 I/O 函数做了很多你在使用低级 read()
s 和 write()
s 时必须自己做的工作。
一些差异是:
read()
不提供字符串终止。你必须自己做。write()
不注意字符串终止。如果你想让它在字符串终止符处停止,那么你必须通过你要求它传输的字节数来控制它。read()
和write()
都不能保证在一次调用中传输请求的全部字节数。如果你想传输特定数量的字节,那么你必须准备好循环。read()
不会在任何特定字符处自动停止,包括换行符- 大多数流都提供缓冲,对您来说是不可见的。如果你想缓冲你的
read()
s 和write()
s 那么你必须自己处理它(但那些功能非常适合它)。
但是,在您的特定情况下,您也犯了语义错误。 write()
和 read()
的第三个参数是要传输的最大字节数——通常是缓冲区的大小——但 sizeof(ptr)
是指针本身的大小,而不是它指向的 space 的大小。