2015-11-23 6 views
0

Я разрабатываю модуль ядра для настраиваемого устройства, которое на самом деле представляет собой 4 * 8-битные порты i-o, подключенные к шине ISA с адресами 0x0120 - 0x0123. Этот драйвер основан на «черепахе» Алессандро Рубини и Джонатана Корбе. Моя ОС - Ubuntu 10.04, ядро ​​- 2.6.32-74 generic, я использую встроенный консольно-ориентированный компилятор gcc. Теперь модуль успешно загружается и выгружается, функции чтения и записи реализованы. Чтение из файла устройства я реализовал так:Данные не могут быть записаны в файл устройства из программы пользовательского пространства

gboolean DataRead (GtkWidget *widget, gpointer data) 
{ 
GtkWidget *statusbar = GTK_WIDGET(data); 
g_assert(statusbar != NULL); 
gchar *StatusText = "Reading data from ADC F-4226"; 
gtk_statusbar_remove (GTK_STATUSBAR(statusbar), StatusBarContext, MessageId); 
StatusBarContext = gtk_statusbar_get_context_id (GTK_STATUSBAR(statusbar), "ET3201-read"); 
MessageId = gtk_statusbar_push (GTK_STATUSBAR(statusbar), StatusBarContext, StatusText); 
ERR = NULL; 
gchar *contents; 
gsize *length = NULL; 
gboolean ReadOK = FALSE; 

ReadOK = g_file_get_contents (DevFile, &contents, length, &ERR); 
if (ReadOK) StatusText = contents; 
    else 
    { 
     g_warning ("Can't open ET3201: %s", ERR->message); 
     StatusText = g_strdup_printf("Error!!! %s: %d, %s", g_quark_to_string (ERR->domain), ERR->code, ERR->message); 
     g_error_free(ERR); 
    } 
    gtk_statusbar_remove (GTK_STATUSBAR(statusbar), StatusBarContext, MessageId); 
    StatusBarContext = gtk_statusbar_get_context_id (GTK_STATUSBAR(statusbar), "ET3201-read"); 
    MessageId = gtk_statusbar_push (GTK_STATUSBAR(statusbar), StatusBarContext, StatusText); 
    g_free(contents); 
} 
return ReadOK; 

}

  • и все работает, статусный отображает строку, которая считывается из устройства. Но когда я попытался написать файл устройства - проблема возникает. Моя функция, которая записывает файл устройства, всегда сообщает об ошибке.

    GError * on_BnStop_clicked (GtkButton *button, gpointer data) 
    { 
    char Data = 255; 
    FILE * ET3201 = NULL; 
    char buf; 
    ERR = NULL; 
    GtkWidget *label = GTK_WIDGET(data); 
    g_assert(label != NULL); 
    if (Started) Started = FALSE; 
    if (! Started) Data = 0;    /* FOR TESTING ONLY!!!*/ 
    gchar *LabelText = "STOP"; 
    gtk_label_set_text(GTK_LABEL(label), LabelText); 
    errno = 0; 
    ET3201=fopen(DevFile,"w");/* Opening the device ET3201 */ 
    ErrorCode = errno; 
    if (ET3201 == NULL) 
    { 
        ERR = g_error_new (G_FILE_ERROR, G_FILE_ERROR_NXIO, "Can't 
    open port ET3201!"); 
        goto fail; 
    } 
    setvbuf(ET3201,&buf,_IONBF,1); /* We remove the buffer from the 
    file i/o */ 
    fwrite(&Data,1,1,ET3201);  /* Writing to device*/ 
    sleep(1); 
    fclose(ET3201);  
    /* g_free(&buf); - leading to "Program aborted" */ 
    fail: 
    return ERR; 
    } 
    

-Так как ET3201 == NULL постоянно. На этом этапе загружается модуль ядра и чтение из него в порядке. После отладки я обнаружил, что функция «Write» в модуле ядра никогда не вызывается, так как она не печатает соответствующее сообщение «printk» в журнале ядра. В отчаянии я попытался сделать это следующим образом:

GError * on_BnStart_clicked (GtkButton *button, gpointer data) 
{ 
    gchar *contents; 
    gssize length = 0; 
    ERR = NULL; 
    GtkWidget *label = GTK_WIDGET(data); 
    g_assert(label != NULL); 
    if (! Started) Started = TRUE; 
    gchar *LabelText = "RUN"; 
    gtk_label_set_text(GTK_LABEL(label), LabelText); 

    contents = g_strdup_printf("/255"); /*FOR TESTING PURPOSES!!!*/ 

    length = sizeof(contents); 

    g_file_set_contents (DevFile, contents, length, &ERR); 

    return ERR; 
} 

и я получаю сообщение об ошибке в статусной: Ошибка: г-файл ошибок кварка: 2, Не удалось создать файл «/dev/ET32010.* *** 8X ': Permission denied Я думаю, это потому, что g_file_set_contents записывает во временный файл, а затем пытается переименовать его в файл устройства, получив «Permission denied». Возможно, это неправильный способ записи файлов устройств, пожалуйста, помогите мне найти правильный ...

Мои вопросы: Почему моя функция on_BnStop_clicked не работает должным образом? Как сделать правильную запись в файл устройства char из программы пользовательского пространства?

Я проверил прав доступа устройство ...

[email protected]:~$ ls -l /dev/ET3201* 
lrwxrwxrwx 1 root root  7 2015-11-23 14:34 /dev/ET3201 -> ET32010 
crw-rw-r-- 1 root staff 250, 0 2015-11-23 14:34 /dev/ET32010 
crw-rw-r-- 1 root staff 250, 1 2015-11-23 14:34 /dev/ET32011 
crw-rw-r-- 1 root staff 250, 2 2015-11-23 14:34 /dev/ET32012 
crw-rw-r-- 1 root staff 250, 3 2015-11-23 14:34 /dev/ET32013 

затем измененный режим в ядре модуль инициализации сценария 666

lrwxrwxrwx 1 root root  7 2015-11-23 22:27 /dev/ET3201 -> ET32010 
crw-rw-rw- 1 root staff 250, 0 2015-11-23 22:27 /dev/ET32010 
crw-rw-rw- 1 root staff 250, 1 2015-11-23 22:27 /dev/ET32011 
crw-rw-rw- 1 root staff 250, 2 2015-11-23 22:27 /dev/ET32012 
crw-rw-rw- 1 root staff 250, 3 2015-11-23 22:27 /dev/ET32013 

и on_BnStart_clicked функция вернула «Отказано в доступе», как это было раньше , но on_BnStop_clicked вывел метод «Write» модуля ядра, а затем успешно завершил работу с ERR == NULL. В конце концов, функция отчетов об ошибках разбилась на «Ошибка сегментации» (сообщение ERR == NULL), но я уже исправил эту ошибку.

+0

У вас есть проверка того, что ваш пользователь может писать в файл? Вы проверяли значение errno, когда fopen терпит неудачу? – jku

ответ

0

Документация g_file_set_contents говорит:

This write is atomic in the sense that it is first written to a temporary file which is then renamed to the final name.

Таким образом, файл /dev/ET32010.****8X фактически височной. И так как создание файлов под /dev обычно разрешено только для root, создание временного файла завершается с «Permission denied».

Даже если сочинительство в /dev будет разрешено, g_file_set_contents будет заменитьустройства файл с регулярно один, который не то, что вы хотите.

Вам необходимо использовать способ записи нижнего уровня в файл устройства. Например, используя fopen + fwrite.

+0

Благодарим вас за помощь! Я протестировал свою функцию on_BnStop_clicked - и теперь он фактически отправляет данные на устройство с помощью функций fopen() и fwrite(). Мой пост теперь содержит рабочий код этой функции. –