Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Bêta ON] La programmation système en C sous Unix

Dans la catégorie "C" par lucas-84

15 janvier 2011 à 11:37:49

Quelques petites nouvelles :

Avec la reprise des cours, je n'ai plus trop le temps de tutoter tout ça. J'ai commencé un chapitre 5 sur les Tubes.

La version en ligne a subi quelques corrections ; et (@totalus) j'ai un peu rajouté des infos là-dessus.

Bonne journée,

Lucas-84

  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
22 janvier 2011 à 11:20:46

Je vous annonce que je viens de terminer la rédaction du chapitre 5 sur les tubes.

Je le corrige en peu et je le place en Bêta !
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
25 janvier 2011 à 18:21:39

Je vous annonce que le titre a été changé.
Désormais, le tutoriel est accessible à toutes les machines Unix.
Donc, les amateurs Mac, BSD et autres, c'est libre ! :D

EDIT : Le chapitre 5 sur les tubes est officiellement en Bêta-Test !
N'hésitez pas à commenter (le chapitre n'est pas encore terminé).
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
30 janvier 2011 à 15:22:59

Bon, je me permets de faire un petit up : je cherche des commentaires pour le chapitre 5 sur les Tubes.
Il ne me manque plus qu'une petite sous-partie sur les tubes nommés, et j'envoie ça en valido !
A vos claviers, je vous attends ! ^^
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
13 mars 2011 à 15:42:11

Re-bonjour tout le monde !
Ca fait longtemps que je n'ai plus actualisé le topic, il faut dire que j'ai perdu un peu de motivation ces dernières semaines.
Mais maintenant, je reviens encore plus fort : le chapitre 5 sur les tubes est fini, complètement fini. A priori, les fautes ont été corrigées, mais ça ne m'étonnerait pas qu'il en reste encore.
D'autre part, j'ai fait quelques modifications dans le reste du tuto, rajoutant des paragraphes de temps en temps, modifiant des passages dont certains m'ont renvoyé des images négatives...

Bref, je vous serais vraiment reconnaissant de commenter ce cinquième chapitre. C'est la dernière étape avant la validation !
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
15 mars 2011 à 19:04:14

Bon, bah tant pis, je vous annonce que le chapitre 5 sur les tubes est d'ores et déjà en ligne.
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
16 mars 2011 à 18:30:14

Je rejoins le premier message de mewtow. :(
Tu parles de beaucoup de choses sans dire vraiment ce que c'est et à quoi ça sert et comment ça fonctionne.
Il y a de l'idée, mais la structure est à revoir je pense, tu parles de choses avant d'autres ou sans rentrer dans les détails 'faites comme ça, point'.

gl
  • Partager sur Facebook
  • Partager sur Twitter
16 mars 2011 à 18:47:09

Même après avoir corrigé le chapitre sur les Processus, ça fait toujours le même effet ?

Je suis d'accord pour dire que les autres ne sont pas vraiment tops, notamment le chapitre sur les threads très critiqué dont je ne suis pas fier du tout (je fais d'ailleurs une maj suite à tes coms...).

J'ai pourtant essayé de regarder un peu la pédagogie des cours "magistraux" pour copier un peu le style d'écriture. Je vais réessayer de bosser sur le chapitre sur les Processus jusqu'à rendre un truc niquel.

N'empêche la comparaison avec le man c'était pas trop sympa... :p

PS : Au fait, quelqu'un aurait-il, dans ce cas-là, des conseils pour rendre le tutoriel moins 'faites comme ça, point'. ?
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
16 mars 2011 à 19:15:23

Citation : lucas-84

N'empêche la comparaison avec le man c'était pas trop sympa... :p


Désolé, j'édite. ^^

Pour les conseils, je pourrai pas trop t'aider, c'est délicat d'aborder ce sujet. A vrai dire, je ne saurais pas moi-même comment l'aborder. :)
Pour le livre de C. Blaess, ça fait un peu le même effet de page de man poussée. D'ailleurs il y a une 3ème version 'Développement système sous Linux' qui est sorti début février. J'ai lu quelques chapitres, mais son livre à l'air baclé, c'est dommage. Il manque des mots, des phrases incorrectes, des codes faux... un peu chiant pour un livre à ce prix là. :(
Et, à vrai dire, je ne sais pas comment on pourrait faire autrement, il n'y a pas de structures de données à montrer ni rien, que des fonctions à expliquer. ;)
  • Partager sur Facebook
  • Partager sur Twitter
16 mars 2011 à 22:01:03

Salut !

Tout d'abord merci d'avoir pris le temps de faire un tutoriel sur ce sujet car c'est assez rare sur internet alors que c'est très intéressant.

Concernant le chapitre sur les threads posix, je proposerai peut-être de commencer par un exemple de thread avant de faire la compilation et la liste des fonctions.

Pourquoi ne pas présenter le code d'un exemple simple mais qui utilise quelques notions. (création de deux threads, petite section critique). Une fois avoir recopié le code, les lecteurs veulent le comprendre. Tu peux alors expliquer chaque point un à un tout en comparant avec les processus lorsque c'est nécessaire.

Une fois qu'ils ont compris ce que leur programme va faire, les gens n'ont qu'une envie c'est de le lancer. Allez hop ! Tu balance la compilation à ce moment là. Une petite commande que les lecteurs n'ont pas forcément envie de comprendre donc pas trop d'explications, pour eux c'est simplement une ligne magique à écrire pour pouvoir enfin voir leur résultat.

Après ça, je pense que tu peux aborder les fonctionnalités plus poussées comme l'attente de fin de threads avec notamment un calcul réparti qui permettrait aux lecteurs d'apercevoir un réel intérêt dans cette technologie.

Voilà c'est juste quelques idées comme ça mais déjà bravo pour t'être lancé dans la rédaction d'un tuto :)

A+


Edit :
Voilà j'ai lu le chapitre 5, voici mes remarques :

- Je trouve l'introduction un peu succincte, tu présentes les tubes sans avoir présenté pourquoi on en aurai besoin. Effectivement on apprend que ça sert à faire communiquer les processus entre eux mais au final le lecteur a besoin d'un exemple qui lui dise "Ah ouais ! P**** mais c'est super balèze de pouvoir faire ça !". Au final pourquoi ne pas garder le même sommaire mais en ajoutant un peu de texte. Pourquoi ne pas commencer par un exemple de problème qui ne serait pas évident à réaliser sans l'utilisation des tubes ? Les gens se demandent alors quelle technologie miracle pourrait venir leur sauver la mise sur ce coup là et lorsque tu leur présente les tubes ils trouvent ça alors comme une merveille offerte par le C !

- Idem que pour le chapitre précédent, je pense que les exemples sont très parlant pour les zéros, déjà parce que c'est agréable de pouvoir voir un résultat, mais aussi parce que ça permet de voir la structure d'un programme. En plus, ça te permet de condenser tes explications en des parties plus claires (exemple 1 => explications des notions ; exemple 2 => explications des notions, ...).
  • Partager sur Facebook
  • Partager sur Twitter
17 mars 2011 à 17:36:39

Bien, merci pour tes conseils, je vais faire un belle MAJ avec tout ça. :)
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
19 mars 2011 à 15:14:14

Bonjour à tous,

Je me permet un petit up pour avoir vos réactions sur le chapitre 2 sur les processus, bien rénové, ainsi que sur le chapitre 3 : Exécuter un programme en cours de mise à jour.

Merci,
Lucas-84
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
19 mars 2011 à 15:40:36

Cette phrase là est à enlever à mon goût : Notez que la fonction fork échoue très peu souvent, il faut vraiment que votre mémoire soit sacrément saturée pour qu'il n'y ait plus de place pour créer un processus !
Imaginons que tu sois sur un système avec très peu de ressources, elle peut très bien échouer facilement. :)

Tu dis : Le paramètre status correspond au code de retour du processus. C'est exactement le même paramètre que la fonction exit (pour laquelle on place habituellement les constantes EXIT_SUCCESS ou EXIT_FAILURE).
On peut très bien retourner ce qu'on veut, histoire de faire une gestion d'erreur ou autre chose. Il faut simplement que le type soit compatible avec int.

Tu parles de wait et tout le tralala, mais qu'est-ce que ça fait si j'oublie de mettre wait ? (bon là je taquine, c'est juste pour dire que ça ne me semble pas clair ^^ ).

Tu dis : n réalité, il est impossible de savoir exactement quel résultat on va avoir quand plusieurs processus exécutent leur code en même temps dans un même terminal : c'est la dure loi de la simultanéité...
Tu pourrais être plus clair je pense. ^^
Et tu peux mettre un résultat, juste prévenir que ce résultat peut s'afficher n'importe comment.

Tu pourrais dire quelque chose sur le fait de tester tous les retours de fonction : est-ce que c'est vraiment utile ?
Tester les retours de fonction, oui, certains sont obligatoire, d'autres... osef ; ça dépend de la gestion d'erreur qu'on veut faire de son programme. Si tu testes absolument toutes tes fonctions, tu auras un code qui augmentera significativement pour, au final, pas grand chose. :)
  • Partager sur Facebook
  • Partager sur Twitter
19 mars 2011 à 15:59:52

Citation

Cette phrase là est à enlever à mon goût : Notez que la fonction fork échoue très peu souvent, il faut vraiment que votre mémoire soit sacrément saturée pour qu'il n'y ait plus de place pour créer un processus !
Imaginons que tu sois sur un système avec très peu de ressources, elle peut très bien échouer facilement. :)



Bon, OK, je vire.

Citation

Tu dis : Le paramètre status correspond au code de retour du processus. C'est exactement le même paramètre que la fonction exit (pour laquelle on place habituellement les constantes EXIT_SUCCESS ou EXIT_FAILURE).
On peut très bien retourner ce qu'on veut, histoire de faire une gestion d'erreur ou autre chose. Il faut simplement que le type soit compatible avec int.



Bon, j'explique ça...

Citation

Tu parles de wait et tout le tralala, mais qu'est-ce que ça fait si j'oublie de mettre wait ? (bon là je taquine, c'est juste pour dire que ça ne me semble pas clair ^^ ).



Tu veux dire que je n'explique pas (ce qui est vrai d'ailleurs :-° ) en quoi un processus en mode zombie est embêtant ?

Citation

Tu dis : n réalité, il est impossible de savoir exactement quel résultat on va avoir quand plusieurs processus exécutent leur code en même temps dans un même terminal : c'est la dure loi de la simultanéité...
Tu pourrais être plus clair je pense. ^^
Et tu peux mettre un résultat, juste prévenir que ce résultat peut s'afficher n'importe comment.



Bon, je recorrige ma correction. :p

Citation

Tu pourrais dire quelque chose sur le fait de tester tous les retours de fonction : est-ce que c'est vraiment utile ?
Tester les retours de fonction, oui, certains sont obligatoire, d'autres... osef ; ça dépend de la gestion d'erreur qu'on veut faire de son programme. Si tu testes absolument toutes tes fonctions, tu auras un code qui augmentera significativement pour, au final, pas grand chose. :)



Bah, c'est assez subjectif comme question. Si on veut distribuer un programme à grande échelle, oui, il est important de bien tester tous les retours de fonction. Maintenant, je ne sais pas ce que les lecteurs comptent faire du programme. D'autre part, si je donne les codes d'erreurs de errno et qu'après je ne le mets pas dans mon code...
Bref, je vois pas trop comment je pourrais différencier les fonctions dont on doit obligatoirement tester le retour et les autres dont on s'en fiche. Je trouve ça un peu trop subjectif, nan ? :( (Bon, OK, j'avoue que j'ai un peu trop forcé sur le retour de wait, surtout que je teste si le paramètre est invalide alors que j'y ai mis NULL)...
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
19 mars 2011 à 16:02:03

Tu testes le retour de printf ? (pwned :p )
  • Partager sur Facebook
  • Partager sur Twitter
19 mars 2011 à 16:23:56

Citation

Tu testes le retour de printf ? (pwned :p )



Bah oui pourquoi ?

Nan mais bon, je prends un exemple : wait. Je teste ou pas ? :(
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
19 mars 2011 à 17:18:00

Bah, comme je te l'ai dit, est-ce que c'est nécessaire ? :)
J'te dis pas faut tester ou pas tester, j'te dis simplement de mettre en garde le lecteur et ensuite à toi de voir comment tu le fais dans ton tuto. ;)
  • Partager sur Facebook
  • Partager sur Twitter
19 mars 2011 à 17:40:20

OK, en tout cas merci pour tes commentaires.
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
21 mars 2011 à 11:05:41

Bon, allez, soyons fous, un petit up. :)

Pour vous dire que le chapitre sur les processus a été agrémenté de quelques paragraphes un peu moins kikoo (un peu trop rébarbatif peut-être aussi...).
Le chapitre sur comment exécuter un programme contient une nouvelle partie sur l'environnement. Je parle désormais de tous les exec, mais ce n'est pas encore fini...

EDIT : Ah, et j'oubliais aussi un chapitre sur la gestion des erreurs.
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
21 mars 2011 à 11:31:59

Et si j'oublie de mettre wait, il se passe quoi ? Les ressources du fils ne sont pas libérées.
Non, c'est faux. Si tu oublies de mettre le wait et que le processus père ne lit pas le retour du processus fils et ensuite que le père se termine sans avoir lu le code de retour du processus fils, c'est le processus init qui va simplement lire le code de retour du processus fils afin de le libérer de son état de zombie.
Si un père se termine avant son fils, c'est le processus init qui 'adopte' le processus fils.
Exemple :

#include <stdio.h> 
#include <stdlib.h>
#include <unistd.h>

int main(void) { 
  pid_t pid;
  
  pid = fork();
  if (pid == -1) {
    perror("fork:");
    return EXIT_FAILURE;
  }
  else if (pid == 0) {
    printf("Processus fils: pid: %ld ppid: %ld\n",
           (long) getpid(), (long) getppid());
    sleep(2); /* Pour que le père se termine avant le fils */
    printf("Processus fils: pid: %ld ppid: %ld\n",
           (long) getpid(), (long) getppid());
  }
  else {
    printf("Processus père: pid: %ld ppid: %ld\n",
           (long) getpid(), (long) getppid());
    sleep(1); /* Histoire qu'il ne se termine pas trop vite pour le ppid fils */
  }
  
  return EXIT_SUCCESS; 
}

Processus père: pid: 1131 ppid: 1123
Processus fils: pid: 1133 ppid: 1131
Processus fils: pid: 1133 ppid: 1

Une remarque sur ton cast aussi, le mieux est de caster dans le plus grand type de la machine pour être sûr que ton pid ne produira pas d'overflow. :)

J'ai pas lu l'autre chapitre (et celui-là je l'ai survolé). :-°
  • Partager sur Facebook
  • Partager sur Twitter
21 mars 2011 à 11:37:12

Citation

Et si j'oublie de mettre wait, il se passe quoi ? Les ressources du fils ne sont pas libérées.
Non, c'est faux. Si tu oublies de mettre le wait et que le processus père ne lit pas le retour du processus fils et ensuite que le père se termine sans avoir lu le code de retour du processus fils, c'est le processus init qui va simplement lire le code de retour du processus fils afin de le libérer de son état de zombie.
Si un père se termine avant son fils, c'est le processus init qui 'adopte' le processus fils.



Figure-toi justement que c'est ce que je suis en train de mettre... ^^

Citation

Une remarque sur ton cast aussi, le mieux est de caster dans le plus grand type de la machine pour être sûr que ton pid ne produira pas d'overflow. :)



De toute façon, je vois mal un PID atteindre ces limites, il faut vraiment que l'administrateur ait sacrément boosté pid_max... (un PID de 2 147 483 647... ??? )
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
22 mars 2011 à 14:59:03

Bon, tant qu'on y est, un petit up (c'est pas interdit au moins :-° ), pour vous dire que le chapitre 3 exécuter un programme est rénové (mais je suis toujours preneur de remarques pour le chapitre sur les processus). Je m'attaque maintenant au plus gros morceau, le chapitre 4 (threads) très très critiqué.
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
22 mars 2011 à 15:08:49

Citation : lucas-84

De toute façon, je vois mal un PID atteindre ces limites, il faut vraiment que l'administrateur ait sacrément boosté pid_max... (un PID de 2 147 483 647... ??? )


On ne sait jamais, précautions, ça ne coûte pas de pain. ;)
  • Partager sur Facebook
  • Partager sur Twitter
22 mars 2011 à 15:42:20

Citation

On ne sait jamais, précautions, ça ne coûte pas de pain. ;)



Si, c'est plus long à écrire... :lol:

Bon, je crois que je vais complétement réorganiser le chapitre sur les threads finalement.
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
26 mars 2011 à 19:18:16

Up :)
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
28 mars 2011 à 0:43:23

J'ai fait une relecture rapide sur ton chapitre sur les processus, il y a des bêtises. :-°
Tu parles de la pile et tu renvoies sur un tuto qui parle de pile et de file mais... ce ne sont pas du tout les mêmes choses dont on parle là. :-°
Un numéro de PID est unique dans le système : il est impossible que deux processus aient un même PID au même moment. En revanche, si à un instant un processus possède un certain PID, il n'y a aucune garantie qu'à l'instant un processus différent n'existera pas avec ce même PID. => Ce qui veut dire que le processus peut changer de pid en cours de route et qu'un autre prenne son pid ? phrase à revoir.
La fonction fork retourne une valeur de type pid_t. Il s'agit d'un entier signé (nombre relatif) => Le type int est un nombre relatif ? :-°
Lorsque le processus fils se termine avant le processus père, il devient un zombie => Faux, il devient zombie même s'il se termine avant son père. Exemple (code bidon qui affiche le pid et mets en pause le processus père) :

>> ./a.out
pere: 2742
fils: 2744

Dans un autre terminal :

>> ps 2744
  PID   TT  STAT      TIME COMMAND
 2744 s000  Z+     0:00.00 (a.out)


J'ai lu en travers mais j'ai vu d'autres erreurs. :(
Désolé, tu dois trouver que je suis chiant... ^^
Bon courage.
  • Partager sur Facebook
  • Partager sur Twitter
29 mars 2011 à 14:25:06

Citation

Un numéro de PID est unique dans le système : il est impossible que deux processus aient un même PID au même moment. En revanche, si à un instant un processus possède un certain PID, il n'y a aucune garantie qu'à l'instant un processus différent n'existera pas avec ce même PID. => Ce qui veut dire que le processus peut changer de pid en cours de route et qu'un autre prenne son pid ? phrase à revoir.



J'ai eu du mal à expliquer. Bon je vais essayer de reformuler.

Citation

Désolé, tu dois trouver que je suis chiant... ^^



Bien au contraire, ça fait avancer le tuto, je ne vais pas te le reprocher en plus...

Pour ce que je n'ai pas cité, j'ai compris la leçon... :-°

Merci,
Lucas-84
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
16 avril 2011 à 9:59:52

Quelques nouveautés :

Chapitre sur les processus : ajout de notes sur le parallélisme/pseudo-parallélisme, implémentation des processus (tables des processus, blocs de contrôle), différences programme/processus, diagramme d'états des processus Unix.

PS : je n'ai pas encore changé ce que Pouet a indiqué dans le précédent message. J'y cours !
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
17 avril 2011 à 17:19:24

Up ?
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
Anonyme
18 avril 2011 à 13:30:01

Quelques détails pour la partie sur les processus :

le bloc de contrôle du processus s'appelle aussi le contexte d’exécution du processus.

Dans la partie espace d'adressage d'un processus, tu a mit le "segment programme", le "segment de donnée" et la pile, mais où est le tas ? Et d’ailleurs, que comptes-tu mettre dans cette partie ? Parce que ça peut aller très loin.

La partie ordonnancement et espace d'adressage pourrait être mise dans la partie présentation des processus. De même, tu pourrais regrouper dans cette partie tout ce qui est valable, même hors linux. Et déplacer le paragraphe commandes de gestion des processus sous unix un peu plus loin dans les parties suivantes.
Histoire de bien séparer ce qui est général à tous les OS et ce qui est particulier aux systèmes UNIX.
  • Partager sur Facebook
  • Partager sur Twitter