2

ユーザー空間からカーネル空間に構造体を渡そうとしています。私は何時間も試していましたが、うまくいきません。これが私がこれまでに行ったことです..

int device_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg){

int ret, SIZE;


switch(cmd){

    case PASS_STRUCT_ARRAY_SIZE:

        SIZE = (int *)arg;
        if(ret < 0){
            printk("Error in PASS_STRUCT_ARRAY_SIZE\n");
            return -1;  
        }
        printk("Struct Array Size : %d\n",SIZE);
        break;

    case PASS_STRUCT:


        struct mesg{
            int pIDs[SIZE];
            int niceVal;
        };

        struct mesg data;

        ret = copy_from_user(&data, arg, sizeof(*data));
        if(ret < 0){
            printk("PASS_STRUCT\n");
            return -1;  
        }

        printk("Message PASS_STRUCT : %d\n",data.niceVal);
        break;

    default :
        return -ENOTTY;
}

return 0;
  }

構造体の定義に問題があります。それを定義する正しい方法は何ですか?int pIDs[SIZE] が必要です。int *pIDs はそれを行いますか (ユーザー空間では pIDs[SIZE] のように定義されます)?

編集:

上記の変更により、このエラーが発生しますか? エラー:「構造体」の前に式が必要ですか?

4

1 に答える 1

1

あなたの質問には、構造の2つのバリアントがあります。

 struct mesg1{
  int *pIDs;
  int niceVal;
 };

 struct mesg2{
  int pIDs[SIZE];
  int niceVal;
 };

それらは違う; mesg1int 配列へのポインタがある場合(これは構造体の外にあります)。それ以外の場合 ( mesg2) 構造体内に int 配列があります。

SIZE が固定されている場合 (モジュールの API で、ユーザー空間とカーネル空間で使用される値と同じ)、2 番目のバリアント ( mesg2) を使用できます。

構造体 ( ) の最初のバリアントを使用するには、次のように構造体自体にmesg1フィールドを追加できます。size

 struct mesg1{
  int pIDs_size;
  int *pIDs;
  int niceVal;
 };

が指す int の数で埋めます*pIDs

PS: そして、構造体 (別名 VLAIS) の途中で可変サイズの配列を持つ構造体を使用しないでください。これは、GCC コンパイラーによる C 言語への独自の、奇妙な、バグのある、文書化されていない拡張機能です。構造体の最後のフィールドのみが、国際 C 標準に従って可変サイズ (VLA) の配列にすることができます。ここにいくつかの例: 1 2

PPS:

VLA で構造体を宣言できます (可変サイズの配列が 1 つしかない場合)。

 struct mesg2{
  int niceVal;
  int pIDs[];
 };

ただし、VLA でそのような構造体にメモリを割り当てるときは注意が必要です。

于 2012-08-26T14:32:38.433 に答える