1

この質問は、Oracle の仮想ボックスで仮想マシンとして実行されている Ubuntu Linux OS のユーザー空間からカーネル空間への ioctl エラー呼び出しに関するものです。モジュール コードがコンパイルされた後、「sudo insmod ioctl_module.ko」コマンドを使用して Linux カーネルにロードされ、以下のメッセージ リストで成功したことがわかります。何らかの理由で、ユーザー空間からカーネル モジュール関数への ioctl 呼び出しで、引数の 1 つが無効であると表示されますが、無効であることがわかりません。(また、スタック オーバーフローに関する質問を投稿したのはこれが 2 回目なので、規則に正しく従っていることを願っています!) ありがとう、カレン

ユーザー レベル コードのエラー メッセージ:

saasbook@saasbook:~/cs552/osPrimer/invokeKernelServices/user_level_code$ ./ioctl_test

testStruct.field1 のサイズ = 1

testStruct.field2 のサイズ = 1

最初の ioctl: 引数が無効です

ioctl_test.c のコード リスト:

https://gist.github.com/KarenWest/6629582

ioctl_module がカーネルにあることがわかります。

/invokeKernelServices$ dmesg

[13563.849593] モジュールをロードしています

[13578.846063] pseudo_device_ioctl

ioctl_module.c の code_listing:

https://gist.github.com/KarenWest/6629557


数日前の質問について、より具体的に説明できるようになりました。ioctl.h ビット定義を使用し、_IOW に #define マクロを使用し、それらをシフトして論理和すると、IOCTL_TEST = 0x4002006 が正しく、cmd = 0x804a030 が正しくないことがわかりますが、cmd が間違っている理由がわかりません。価値。cmd は、上記の ioctl エントリ ポイントへの引数です。

static int pseudo_device_ioctl(struct inode *inode, struct file *file,
            unsigned int cmd, unsigned long arg)

そこで、proc_fs.h 入力ファイルの proc_dir_entry 構造体を調べました。この構造体の proc_fops ポインターは、ioctl エントリ ポイント関数に設定され、pseudo_dev_proc_operations は file_operations 構造体に初期化され、proc_entry は proc_dir_entry 構造体へのポインターとして初期化されます (すべて上記の git のコード リンクで)、これらはすべて ioctl_module.c の initialization_routine() で初期化されています。ioctl_test.c レベルで実行されているコードが呼び出されると、この ioctl が正しい値で設定されていることがわかりました。それを私のioctl関数に向けるように設定する必要があります。しかし、ioctl 関数のセットアップ (cmd) に送信された引数が正しくなく、IOCTL_TEST と一致しないため、失敗します。

pseudo_dev_proc_operations.unlocked_ioctl = pseudo_device_ioctl;
pseudo_dev_proc_operations.compat_ioctl = pseudo_device_ioctl;

proc_entry = create_proc_entry("ioctl_test", 0666, NULL);
proc_entry->proc_fops = &pseudo_dev_proc_operations;

そのため、proc_fs.h の proc_fops ポインター (これは、ioctl pseudo_device_ioctl 関数に渡される pseudo_dev_proc_operations に初期化されます) をたどって、処理中に cmd 引数が混乱する理由を確認しました。なぜこれが起こっているのかわかりません。

どこが間違っているのかを理解するのに役立つ可能性のあるコメントが他にある場合は、お知らせください。ありがとう!カレン


これは役立つかもしれません-これを読んでください:

「Linux カーネル モジュール プログラミング ガイド:

第7章 デバイスファイルとの対話

7.1. デバイス ファイルとの対話 (書き込みと IOCTL)"

4

1 に答える 1

0
#define _IOC_NRBITS     8
#define _IOC_TYPEBITS   8

/*
 * Let any architecture override either of the following before
 * including this file.
 */
#ifndef _IOC_SIZEBITS
# define _IOC_SIZEBITS  14
#endif
#ifndef _IOC_DIRBITS
# define _IOC_DIRBITS   2
#endif

#define _IOC_NRMASK     ((1 << _IOC_NRBITS)-1)
#define _IOC_TYPEMASK   ((1 << _IOC_TYPEBITS)-1)
#define _IOC_SIZEMASK   ((1 << _IOC_SIZEBITS)-1)
#define _IOC_DIRMASK    ((1 << _IOC_DIRBITS)-1)

#define _IOC_NRSHIFT    0
#define _IOC_TYPESHIFT  (_IOC_NRSHIFT+_IOC_NRBITS)
#define _IOC_SIZESHIFT  (_IOC_TYPESHIFT+_IOC_TYPEBITS)
#define _IOC_DIRSHIFT   (_IOC_SIZESHIFT+_IOC_SIZEBITS)

/*
 * Direction bits, which any architecture can choose to override
 * before including this file.
 */
#ifndef _IOC_NONE
# define _IOC_NONE      0U
#endif
#ifndef _IOC_WRITE
# define _IOC_WRITE     1U
#endif
#ifndef _IOC_READ
# define _IOC_READ      2U
#endif

#define _IOC(dir,type,nr,size) \
        (((dir)  << _IOC_DIRSHIFT) | \
         ((type) << _IOC_TYPESHIFT) | \
         ((nr)   << _IOC_NRSHIFT) | \
         ((size) << _IOC_SIZESHIFT))

#define _IOC_TYPECHECK(t) (sizeof(t))
#define _IOR(type,nr,size)      _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOW(type,nr,size)      _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))**
#define _IOWR(type,nr,size)     _IOC(_IOC_READ|_IOC_WRITE,(type),nr),_IOC_TYPECHECK(size)))

ご覧のとおり、ユーザー空間 ioctl_test.c で使用する _IOW とモジュール ioctl 関数で使用する _IOWR は、同じ引数に対して異なる値に評価されます。したがって、スイッチケースは失敗しています。モジュール内でも _IOW を使用してみてください。

于 2013-09-20T07:03:00.803 に答える