2012-08-26 2 views
2

J'essaie de passer une structure de l'espace utilisateur vers l'espace noyau. J'avais essayé pendant de nombreuses heures et ça ne marche pas. Voici ce que j'ai fait jusqu'à présent.Passage de la structure au pilote de périphérique via IOCTL

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

J'ai du mal à définir la structure. Quelle est la bonne façon de le définir? Je veux avoir des pID int [TAILLE]. Est-ce que int * pID le fera (dans l'espace utilisateur, il est défini comme pIDs [SIZE])?

EDIT:

Avec le changement ci-dessus je reçois cette erreur? erreur: expression attendue avant 'struct' des idées?

+0

en ce qui concerne le cas PASS_STRUCT, vous devez définir "données" comme struct, pas un pointeur vers struct, puis passer correctement la taille à copy_from_user. Votre problème est plus probable C. imho vous devriez être plus expérimenté avec C avant de creuser le noyau. – sardok

+0

Comment pensez-vous que je devrais définir cette fonction, #define PASS_STRUCT _IOW (MY_MAGIC, 2, struct mesg *)? – user340

+0

J'ai défini les données comme struct, (struct mesg data;). Mais donne l'erreur d'erreur: la taille de stockage de «données» n'est pas connue .. toutes les idées? – user340

Répondre

1

Il existe deux variantes de la structure dans votre question.

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

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

Ils sont différents; dans le cas de mesg1 vous avez un pointeur sur int array (qui est en dehors de la structure). Dans l'autre cas (mesg2) il y a un tableau int à l'intérieur de la structure.

Si votre TAILLE est fixe (dans l'API de votre module, la même valeur que celle utilisée dans l'espace utilisateur et noyau), vous pouvez utiliser la deuxième variante (mesg2).

Pour utiliser première variante de la structure (mesg1), vous pouvez ajouter le champ size à la structure elle-même, comme:

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

et le remplir avec le comte de ints, pointé par *pIDs.

PS: Et s'il vous plaît, jamais utiliser des structures avec des tableaux de taille variable au milieu de la struct (aka VLAIS). Ceci est propriétaire, wierd, buggy et non-documented extension au langage C par le compilateur GCC. Seul le dernier champ de struct peut être array with variable size (VLA) selon la norme internationale C. Quelques exemples ici: 12

PPS:

Vous pouvez vous déclariez struct avec VLA (s'il n'y a qu'un seul tableau de taille variable):

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

mais vous devez être prudent lors de l'allocation mémoire Pour une telle structure avec VLA

+0

Eh bien, je veux utiliser le type mesg2. Avant de passer la structure, je prévois de passer la TAILLE. est-ce que ça marchera? – user340

+0

non, vous devez soit corriger SIZE à l'étape de conception, puis ne jamais le transmettre. Ou vous devriez réécrire votre structure de telle manière que le tableau sera le dernier champ de la structure. – osgx

+0

propriétaire? :-) – Igor

Questions connexes