0

カスタム デバイス用のカーネル モジュールを開発しています。実際には、アドレス 0x0120 ~ 0x0123 の ISA バスに 4*8 ビットの io ポートが接続されています。このドライバーは、Alessandro Rubini と Jonathan Corbet による「スカル」に基づいています。私のOSはUbuntu 10.04で、カーネルは2.6.32-74ジェネリックで、組み込みのコンソール指向コンパイラ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 のように常に。この時点でカーネル モジュールがロードされ、そこからの読み取りは問題ありません。デバッグ後、カーネル ログに対応する「printk」メッセージが出力されないため、カーネル モジュールの「Write」関数が呼び出されないことがわかりました。必死になって、私はこのようにしようとしました:

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

ステータスバーにエラーメッセージが表示されます: Error: g-file-error-quark: 2, Failed to create file '/dev/ET32010.****8X': Permission denied g_file_set_contents が一時ファイルに書き込むためだと思います次に、「許可が拒否されました」というデバイスファイルに名前を変更しようとします。これはデバイス ファイルの書き方が間違っている可能性があります。正しい方法を見つけるのを手伝ってください...

私の質問: 関数 on_BnStop_clicked が正しく動作しないのはなぜですか? ユーザー空間プログラムからcharデバイスファイルに正しく書き込む方法は?

デバイスのアクセス権を確認しました...

master@master-desktop:~$ 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

次に、カーネルモジュールのinitスクリプトでモードを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 はカーネル モジュールの「書き込み」メソッドを呼び出し、ERR == NULL で正常に完了しました。結局、エラー報告機能は「セグメンテーション違反」(reporting ERR == NULL) でクラッシュしましたが、私はすでにこのバグを修正しました。

4

1 に答える 1