Causes d'un kmalloc qui retourne NULL

Bonjour,

Je suis présentement en train de débugger des drivers et je me rends compte qu’une des causes des instabilités est le fait qu’un kmalloc fini par retourner un pointeur nul lors de l’allocation de mémoire.

Je me doute très bien qu’une des causes vient du fait qu’il ne reste plus de mémoire disponible mais existe-t-il d’autres situations où cela peut se produire. J’ai cherché sur le net et généralement tout ce que je trouve c’est un truc du genre, en cas d’erreur, un pointeur null sera retourné…

Bref si vous connaissez les autres causes d’erreur s’il y en a, je serais très intéressé de les connaître.

Merci à l’avance!

huuuummm tu trouvera surement plus d’aide sur le forum programmation
ici, on part d’un plus haut niveau, celui du système :slight_smile: certain d’entres nous programmes mais ce n’est pas vraiment l’objectif de ce forum

je suis même pas sûr que tu trouve sur clubic en fait :neutre:
voir peut être à te tourner vers la lkml ?

Tu alloues avec quelles options ? (GFP_KERNEL ? )

En effet j’ignorais sur lequel des deux le mettre mais je l’ai mis ici car il me semble que j’avais déjà vu quelques personnes assez douées au niveau du kernel.

v_aketor: Dans le cas qui semble me causer problème c’est effectivement un GFP_KERNEL, j’essais d’utiliser GFP_ATOMIC que dans des interrupts handlers ou bien lorsque je ne veux vraiment pas que le kmalloc s’endorme à un endroit donné.

Pour ce qui est de la lkml, j’y ai en effet pensé mais j’ai surtour fait des recherches sur la mailing list sans rien trouver, peut-être que je devrais poser ma question à cet endroit :confused:

En tous cas merci!

Ben normalement tu as tout bon au niveau malloc. Ce qui veut dire que tu es sans doute un saut de page, donc il te faut rajouter une page.


Sinon kmalloc ne peut allouer que des puissances de 2 et moins de 128ko. l'allocation est indeterminée dans ce cas, mais possible que ça retourne null.

Au niveau de la taille maximale, ce n’est qu’une petite structure qui est très certainement plus petites que 128 Ko. En gros elle contient une list_head, un pointeur vers une autre structure ainsi qu’un unsigned long. Le kmalloc est en effet assez solicité mais il y a un kfree à chaque fois donc je ne crois pas qu’on consomme toute la mémoire, j’ignore juste si le kmalloc est fait pour soutenir une forte charge. Ce qui est bizarre c’est que le tout fonctionne pendant 15-20k copies (il s’agit principalement des opérations de copy de mémoire host vers IO ou IO vers host) et qu’à un certain moment donné je recois un pointeur null.

Peux-tu me préciser ce que tu entends par ajouter une page? Je croyais que ce genre de processus se faisait de manière autonome avec le slab allocator.

Merci beaucoup de ton aide v_atekor, c’est très apprécié.

Bon ok, on fait simple : pas d’allocation dynamique dans le noyau, sauf raisons graves et serieuses, avec un mot des parents. Je pense que ca merde pour ca. les enchainements kmalloc/kfree a eviter;

J avance une explication boiteuse : tes premieres allocations se font toutes dans la meme page de memoire. Je suspecte que le free ne desaloue pas immediatement la memoire, et donc que tu satures ta page. Il faut un peu de temps a la vmm pour te trouver une autre page libre et pendant ce temps tu te retrouves avec un pointeur nul. (la fonction n est pas suspendu dans le noyau contrairement a une fonction userland puisque les deux fonctions sont dans le noyau (et de meme priorite ???) )
Edité le 11/09/2007 à 15:40


Les pages : la memoire virtuelle (reelle+swap) que tu utilises est divisee en pages. Chaque programme se voit alouer des pages dans lesquels se trouve la memoire qu'il utilise (c'est une division de la memoire totale). Sauf que dans le noyau ... et bien le gros probleme est que le noyau n'est pas un processus , donc ce qui est transparent en userland peut poser problème dans le noyau. Par ex. si tu as besoin de plus de memoire tu as besoin d'autres pages, et cette autre page n'est pas forcement contigue, donc gare aux enchainements pointeur=pointeurs++ (marche pas forcement dans le noyau)

plus d’info ici

Merci beaucoup pour les informations. Sinon pour éviter de devoir allouer constament de la mémoire et la libérer par après, est-ce qu’un memory pool pourrait être une bonne manière de faire ou bien s’il vaut mieux redesigner directement une partie du driver pour éviter ce genre de truc?

En tous cas c’est très éducatif parler avec toi! J’en ai appris sur le comportement de kmalloc.

héhéhé y’a de la competence sur ce forum ! faut pas croire !

bon… c’est juste dommage qu’il soit un fan de vim… a part ca, il serait le gendre ideal :ane:
ca gache un peu quoi
Edité le 11/09/2007 à 19:46

Heu … ca depend de ce que tu veux faire, je ne peux pas te dire comme ca.

Moi je suis plutot du genre a faire une allocation unique et a reecrire toujours au meme endroit, mais ca ne s’applique pas forcement dans ton cas.

kp2 : :paf: :wink:

j’avas oublié la roquette en effet :smiley:

laquelle ??

http://www.vert-desir.com/images/produits/roquette300.jpg

rooh… spa bien de se moquer… surtout avec des blagues aussi faciles et lourdes :paf:

hey va pas vexer notre kernel hacker steup :o ^^’

:ane:

(C’t faaââââacil) :ane: :nexath

mdr:D

v_atekor: C’est aussi la solution que je préconise mais je dois faire une petite étude s’il s’agit d’une solution viable dans mon cas. Merci encore!

Argl j’arrive après la bataille :frowning:
v_atekor a déjà répondu :slight_smile:
La gestion de la mémoire dans le noyau c’est un peu comme en fortran77 pour les vieux qui connaissent:
Pas d’alloc dynamique donc des designs du style “j’alloue ça au début et si j’ai besoin j’alloue de nouveau le double”. Par contre, comme là si bien expliqué notre v_atekor national :slight_smile: il faut faire attention aux trous entre les pages. Doucement sur les calculs avec les poiteurs.
Bref, on voti beaucoup de code dans le noyau qui alloue tout une fois pour toutes. Si on commençait à mettre de l’alloc dynamique aussi bas niveau, il faudrait aussi se demander “que faire quand ils n’y a plus de telles pages à allouer”…On est sorti…donc on alloue au début.

Ouais c’est ce que j’ai compris, il faut penser drôlement différemment au niveau de la gestion de la mémoire dans le kernel. L’allocation était en fait pour copier le contenu d’un array qu’on recoit sous forme de pointeur et qu’on ne veut pas manipuler directement (un array qui part du user space au départ).

Le “problème” est que la taille de cet array varie donc il devient un peu plus embettant d’allouer une fois pour toute. C’est pourquoi j’avais pensé à utiliser un memory pool qui en théorie est beaucoup plus rapide et a plus de chance de réussir qu’un kmalloc (je vous dis ce que j’ai compris de la chose, je me trompe peut-être). D’un autre côté je n’aime pas énormément cette méthode dans la mesure où la taille du pool reste statique. Et de ce que j’ai lu du livre d’Oreilly, il vaut mieux s’en servir réellement en dernier recours.

Bref je vais regarder ce que je peux faire :stuck_out_tongue:

etpuis : regarder comment c’est fait dans hum un driver simple du noyau? (ça existe sisi)