额外的 memset() 导致系统调用 open() 失败
我按照教程 /dev 中创建了一个节点title="Look at Example 4-1.chardev.c">这里 (chardev.c),我尝试访问使用以下命令创建的 /dev/chardev
中的设备代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h> //perror(), errno
#include <string.h>
#define RSIZE 50
int main()
{
int fd,err_save;
char receive_buff[RSIZE];
//open device and check for error msg
fd = open("/dev/chardev", "rw");
err_save = errno;
if (fd < 0)
{
perror("open perror");
printf("error opening device, fd = %d, err_save = %d \n", fd,err_save);
}
else
{printf("Device opened\n");}
//read device and check for error msg
//memset(receive_buff, 0, sizeof(receive_buff)); //<--- strange
read(fd, receive_buff, RSIZE);
err_save = errno;
if (fd < 0)
{
perror("read perror");
printf("error reading device, fd = %d, err_save = %d \n", fd,err_save);
}
else
{
printf("Device read successful : %s\n",receive_buff);}
//close device and check for error msg
fd = close(fd);
err_save = errno;
if (fd < 0)
{
perror("close perror");
printf("error closing device, fd = %d, err_save = %d \n", fd,err_save);
}
else
{printf("Device closed\n");}
return 0;
}
成功结果:
Device opened
Device read successful : I already told you 7 times Hello world!
w�0 ����
Device closed
但是,当 memset(receive_buff, 0, sizeof(receive_buff));
取消注释时,我得到以下信息:
open perror: File exists
error opening device, fd = -1, err_save = 17
read perror: Bad file descriptor
error reading device, fd = -1, err_save = 9
close perror: Bad file descriptor
error closing device, fd = -1, err_save = 9
问题:额外的 memset()
如何导致 open()
失败?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
open
将一个整数作为第二个参数(您可能会将其与fopen
混淆)。您的open
行应该是:添加和删除代码时它工作或失败的原因与
"rw"
地址的不可预测值有关,这种情况可能会发生当memset
被删除时,成为open
的有效值。open
takes an integer as the second parameter (you're getting it confused withfopen
). Youropen
line should be:The reason it works or fails as code is added and removed has to to with the unpredictable value of the address of
"rw"
, which could happen to be a valid value foropen
whenmemset
is removed.您需要在
open
的第二个参数中传递一个整数,在您的情况下它是O_RDWR
。调用应该是:阅读手册:
man 2 open
。链接: http://linux.die.net/man/2/open更新
您错误地检查了读取错误。您的代码:
如果出现读取错误
read
调用将返回-1
因此您应该检查read
的返回值而不是>fd
。实现:您的代码可以正确运行,因为第二个参数只是一个设置了位值的整数,它具有特定的解释。您传递一个地址(加载的可执行文件中字符串的基地址),它也是一个整数,并且设置了一些特定字段和未设置一些特定字段。无法判断这些位是否是通过正确地对标志进行“或”运算而设置的,还是恰好设置了特定位的随机整数。因此,该函数将通过检查哪个位被设置或未设置来解释随机整数,并按照分配给每个位的解释工作。
此外,在读取文件时,您不会检查读取是否成功。如果随机整数碰巧具有用于读取文件集的正确位,那么它将正确读取。
You need to pass an integer in the second parameter of
open
, In your case it isO_RDWR
. The call should be:Read manual:
man 2 open
. Link: http://linux.die.net/man/2/openUPDATE
You incorrectly check for read errors. Your code:
If there is a read error
read
call will return-1
therefore you should check the return value ofread
and not thefd
. Make it:Your code runs correctly because the second parameter is simply an integer with its bit values set, which has specific interpretation. You pass an address (the base address of the string in the loaded executable), which is also an integer, and has some specific fields set and some unset. It is impossible to tell that if the bits were set by correctly ORing the flags or was a random integer which happens to have specific bits set. Therefore the function will interpret the random integer by checking which bit is set or not and work as per the interpretation assigned to each bit.
Also when reading from the file you do not check if the read was successful. If in case the random integer happens to have the correct bits for reading the file set, then it will read correctly.
要么你的编译器没有警告你它应该警告的事情,要么你忽略了它给你的警告。
其他人已经告诉过您 open() 的第二个参数是 int;传递字符串文字是不正确的。
open(2)
手册页指出您需要:您的编译器应该至少警告您,
open()
功能。嗯,我刚刚检查过;我很失望地看到 gcc 默认情况下不这样做。 (在 C99 中,调用没有可见声明的函数是违反约束的行为,但大多数编译器默认情况下不支持 C99(如果有的话)。)您可能正在使用 gcc。启用更多警告(以
-Wall -Wextra
开头)并注意编译器告诉您的内容。并阅读您使用的任何函数的手册页,以了解需要哪些标头。Either your compiler isn't warning you about things it should, or you're ignoring the warnings it does give you.
Others have already told you that
open()
's second argument is an int; passing a string literal is incorrect.The
open(2)
man page says that you need:Your compiler should have at least warned you that there's no visible declaration for the
open()
function. Hmm, I just checked; I'm disappointed to see that gcc doesn't do this by default. (In C99, calling a function with no visible declaration is a constraint violations, but most compilers don't support C99 by default, if at all.)You're probably using gcc. Enable more warnings (start with
-Wall -Wextra
) and pay attention to what the compiler tells you. And read the man pages for any functions you use to see what headers are required.