额外的 memset() 导致系统调用 open() 失败

发布于 2024-12-03 01:53:31 字数 2031 浏览 2 评论 0 原文

我按照教程 /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() 失败?

I've created a node in /dev by following the tutorial here (chardev.c), I tried to access the device in /dev/chardev I created by using the following code :

#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;
}    

successful result:

Device opened
Device read successful : I already told you 7 times Hello world!
w�0 ����
Device closed

However, when memset(receive_buff, 0, sizeof(receive_buff)); is uncommented, I get the following:

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 

Question: How does the additional memset() causes the open() to fail ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

下雨或天晴 2024-12-10 01:53:31

open 将一个整数作为第二个参数(您可能会将其与 fopen 混淆)。您的 open 行应该是:

fd = open("/dev/chardev", O_RDWR);

添加和删除代码时它工作或失败的原因与 "rw" 地址的不可预测值有关,这种情况可能会发生当 memset 被删除时,成为 open 的有效值。

open takes an integer as the second parameter (you're getting it confused with fopen). Your open line should be:

fd = open("/dev/chardev", O_RDWR);

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 for open when memset is removed.

您的好友蓝忘机已上羡 2024-12-10 01:53:31

您需要在open的第二个参数中传递一个整数,在您的情况下它是O_RDWR。调用应该是:

fd = open ("/dev/chardev", O_RDWR);

阅读手册:man 2 open。链接: http://linux.die.net/man/2/open

更新

您错误地检查了读取错误。您的代码:

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);
}

如果出现读取错误 read 调用将返回 -1 因此您应该检查 read 的返回值而不是 >fd。实现:

read_bytes = read(fd, receive_buff, RSIZE);
err_save = errno;
if (read_bytes < 0)
{
  perror("read perror");
  printf("error reading device, fd = %d, err_save = %d \n", fd,err_save);
}

您的代码可以正确运行,因为第二个参数只是一个设置了位值的整数,它具有特定的解释。您传递一个地址(加载的可执行文件中字符串的基地址),它也是一个整数,并且设置了一些特定字段和未设置一些特定字段。无法判断这些位是否是通过正确地对标志进行“或”运算而设置的,还是恰好设置了特定位的随机整数。因此,该函数将通过检查哪个位被设置或未设置来解释随机整数,并按照分配给每个位的解释工作。

此外,在读取文件时,您不会检查读取是否成功。如果随机整数碰巧具有用于读取文件集的正确位,那么它将正确读取。

You need to pass an integer in the second parameter of open, In your case it is O_RDWR. The call should be:

fd = open ("/dev/chardev", O_RDWR);

Read manual: man 2 open . Link: http://linux.die.net/man/2/open

UPDATE

You incorrectly check for read errors. Your code:

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);
}

If there is a read error read call will return -1 therefore you should check the return value of read and not the fd. Make it:

read_bytes = read(fd, receive_buff, RSIZE);
err_save = errno;
if (read_bytes < 0)
{
  perror("read perror");
  printf("error reading device, fd = %d, err_save = %d \n", fd,err_save);
}

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.

a√萤火虫的光℡ 2024-12-10 01:53:31

要么你的编译器没有警告你它应该警告的事情,要么你忽略了它给你的警告。

其他人已经告诉过您 open() 的第二个参数是 int;传递字符串文字是不正确的。

open(2) 手册页指出您需要:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

您的编译器应该至少警告您,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:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文