Portage du code de l’espace utilisateur dans l’espace kernel

J’ai un grand système écrit principalement en C qui fonctionnait dans l’espace utilisateur jusqu’à maintenant. Maintenant, je dois comstackr le code en tant que module du kernel. Pour cela, je devrais au moins réécrire le code et remplacer les fonctions comme malloc , calloc , free , printf par leurs équivalents du kernel, car ce ne sont que des fonctions d’espace utilisateur. Le problème est que je ne dispose pas du code source de certaines bibliothèques personnalisées utilisées dans le système et que ces bibliothèques appellent malloc etc. dans leurs fonctions. Donc, fondamentalement, je pourrais avoir besoin de réimplémenter toute la bibliothèque.

Maintenant, la question: est-ce que ce sera un hack vraiment sale, si kmalloc ma propre implémentation de malloc comme un wrapper autour de kmalloc , quelque chose comme ceci:

 void *malloc(size_t size) { return kmalloc(size, GFP_USER); } 

Ensuite, associez cette implémentation au code système, ce qui éliminera toutes les erreurs du symbole Inconnu dans le module .

En fait, je pensais que ce serait un problème courant et que quelqu’un aurait déjà écrit une telle enveloppe de kmalloc, mais je google depuis quelques jours maintenant et je n’ai rien trouvé d’utile.

EDIT: La raison en est que le système dont je parle était une application en temps réel exécutée sur le système d’exploitation temps réel de VxWorks et que nous souhaitons maintenant le porter pour qu’il soit utilisé sur Linux RTAI, les applications s’exécutant principalement dans l’espace kernel. Mais je suppose qu’il y a une possibilité d’avoir du temps réel dans l’espace utilisateur, donc je devrais probablement faire comme Mike l’a suggéré et séparer le code en parties du kernel et de l’espace utilisateur et communiquer entre elles avec de la mémoire partagée.

Je n’ai jamais vu ça auparavant. Je devais faire quelque chose de similaire à un travail précédent (dans nos téléphones, pour des raisons d’économie d’énergie, nous devions porter une partie du code de l’espace utilisateur à partir du kernel) mais c’est comme ça que je l’ai fait. code et déplacé, et une petite partie à cela.

Lorsque je l’ai fait, j’ai changé les appels d’espace utilisateur vers les appels du kernel pour plusieurs raisons principales:

  1. C’était moins déroutant (les autres utilisateurs du code ne se demandaient pas pourquoi j’appelais “malloc” du kernel)

  2. malloc et kmalloc ne fonctionnent pas exactement de la même manière. Ce que je veux dire par là est

    2a. kmalloc prend un paramètre flags , dans votre exemple ci-dessus vous l’avez codé en dur. Et si vous décidiez plus tard de vouloir le changer dans certains endroits et pas dans d’autres? (en supposant que vous avez un certain nombre d’endroits différents où vous obtenez de la mémoire dynamic).

    2b. kmalloc ne vous donne pas la mémoire de la même manière que malloc . malloc() vous donnera le nombre d’octets que vous passez en size_t size . kmalloc() , par contre, se trouve dans le kernel et traite donc de la mémoire physique du système, qui n’est disponible que par morceaux de taille page; ainsi, lorsque vous appelez kmalloc() vous ne recevrez que certains tableaux d’octets de taille fixe prédéfinis. Si vous n’en êtes pas conscient, vous pouvez demander un peu plus sur un morceau particulier et obtenir ainsi beaucoup plus de mémoire que nécessaire. Un port direct de votre code ne vous en protégera pas.

    2c. Les fichiers d’en-tête doivent également changer. Évidemment, vous ne pouvez pas inclure dans le kernel, donc, juste parce que vous avez “enveloppé” l’appel malloc, vous devez toujours remplacer les fichiers d’en-tête.

exemple rapide de mon propos en 2b ci-dessus:

 void * stuff; stuff = kmalloc(1,GFP_KERNEL); printk("I got: %zu bytes of memory\n", ksize(stuff)); kfree(stuff); 

Pour afficher la quantité réelle de mémoire allouée:

 [90144.702588] I got: 32 bytes of memory 

de toute façon … techniquement, comment vous le décrivez, ça devrait marcher. Les deux prennent une size_t et renvoient un void * pour que cela fonctionne; mais sachez que plus vous déplacez de code dans le kernel, moins les choses deviennent déterministes, et que malloc() <=> kmalloc() n’est pas aussi kmalloc() qu’il le semble.

En essayant de rendre mon code RTAI compilable à la fois dans les espaces utilisateur et kernel (ainsi que de travailler avec POSIX), j’ai développé URT qui fait essentiellement ce que vous demandez. Il s’agit d’un niveau d’abstraction léger sur les systèmes en temps réel (et même sur les fonctions RTAI incompatibles entre l’espace utilisateur et l’espace kernel).