Дополнительный memset () приводит к сбою системного вызова open () - PullRequest
0 голосов
/ 07 сентября 2011

Я создал узел в /dev, следуя инструкции здесь (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()?

Ответы [ 3 ]

5 голосов
/ 07 сентября 2011

open принимает целое число в качестве второго параметра (вы путаете его с fopen).Ваша строка open должна быть:

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

Причина, по которой он работает или не срабатывает при добавлении и удалении кода, связана с непредсказуемым значением адреса "rw", которое может оказатьсядопустимое значение для open при удалении memset.

2 голосов
/ 07 сентября 2011

Вам нужно передать целое число во втором параметре open, в вашем случае это O_RDWR. Вызов должен быть:

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

Прочтите руководство: man 2 open. Ссылка: http://linux.die.net/man/2/open

UPDATE

Вы неправильно проверяете наличие ошибок чтения. Ваш код:

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

Ваш код работает правильно, потому что второй параметр - это просто целое число с установленными значениями битов, которое имеет определенную интерпретацию. Вы передаете адрес (базовый адрес строки в загруженном исполняемом файле), который также является целым числом и имеет определенные определенные поля, установленные и некоторые неустановленные. Невозможно сказать, что, если биты были установлены правильно ИЛИ флагами или были случайным целым числом, в котором, как оказалось, установлены конкретные биты. Поэтому функция будет интерпретировать случайное целое число, проверяя, какой бит установлен или нет, и работает в соответствии с интерпретацией, назначенной для каждого бита.

Также при чтении из файла вы не проверяете, было ли чтение успешным. Если случайное целое число имеет правильные биты для чтения набора файлов, оно будет считываться правильно.

1 голос
/ 07 сентября 2011

Либо ваш компилятор не предупреждает вас о том, что он должен, либо вы игнорируете предупреждения, которые он вам дает.

Другие уже говорили вам, что второй аргумент open() - это int;неправильная передача строкового литерала.

Страница man open(2) говорит, что вам нужно:

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

Ваш компилятор должен хотя бы предупредить вас, что нетвидимое объявление для функции open().Хм, я только что проверил;Я разочарован тем, что gcc не делает этого по умолчанию.(В C99 вызов функции без видимого объявления является нарушением ограничения, но большинство компиляторов не поддерживают C99 по умолчанию, если вообще.)

Возможно, вы используете gcc.Включите больше предупреждений (начните с -Wall -Wextra) и обратите внимание на то, что говорит вам компилятор.И прочитайте справочные страницы для любых функций, которые вы используете, чтобы увидеть, какие заголовки требуются.

...