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

时间:2011-09-07 03:34:41

标签: c linux kernel system-calls memset

我已按照教程here (chardev.c)/dev中创建了一个节点,我尝试使用以下代码访问我创建的/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()失败?

3 个答案:

答案 0 :(得分:5)

open将整数作为第二个参数(您将其与fopen混淆)。您的open行应为:

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

在添加和删除代码时它工作或失败的原因必须是"rw"地址的不可预测值,这可能恰好是open memset的有效值删除。

答案 1 :(得分:2)

您需要在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);
}

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

同时从文件中读取时,不检查读取是否成功。如果随机整数恰好具有用于读取文件集的正确位,则它将正确读取。

答案 2 :(得分:1)

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

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

open(2)手册页说明您需要:

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

您的编译器应该至少警告过您open()函数没有可见的声明。嗯,我刚检查过;我很失望地看到gcc默认不这样做。 (在C99中,调用没有可见声明的函数是违反约束的,但是大多数编译器默认情况下不支持C99,如果有的话。)

你可能正在使用gcc。启用更多警告(以-Wall -Wextra开头)并注意编译器告诉您的内容。并阅读手册页,了解您用于查看所需标题的任何函数。