<<, cpp, file descriptors
#include <sys/inode.h>
di_mode = 0x41ed == 040755                 /* mode de "/" */
                 == IFDIR 
                  | IREAD | IWRITE | IEXEC 
                  |(IREAD | IEXEC) >> 3
                  |(IREAD | IEXEC) >> 6
di_mode = 0x41ed == 0100755               /* mode de "/vmunix" */
                 == IFDIR 
                  | IREAD | IWRITE | IEXEC 
                  |(IREAD | IEXEC) >> 3
                  |(IREAD | IEXEC) >> 6
/usr/include/sys/inode.h.
#define IFPORT 0010000 /* port (named pipe) */ #define IFCHR 0020000 /* character special */ #define IFDIR 0040000 /* directory */ #define IFBLK 0060000 /* block special */ #define IFREG 0100000 /* regular */ #define IFLNK 0120000 /* symbolic link */ #define IFSOCK 0140000 /* socket */ #define IFPIPE 0160000 /* pipe */ #define ISUID 04000 /* set user id on execution */ #define ISGID 02000 /* set group id on execution */ #define ISVTX 01000 /* save swapped text even after use */ #define IREAD 0400 /* read, write, execute permissions */ #define IWRITE 0200 #define IEXEC 0100
chmod permet de modifier les accès d'un fichier.
% ls -ld Mail drwxr--r-- 4 levy 512 Oct 30 15:48 Mail % chmod go-r Mail % ls -ld Mail drwx------ 4 levy 512 Oct 30 15:48 Mail
chmod permet de modifier les accès d'un fichier.
read, write, execute. Pour un directory, 
execute veut dire qu'on peut faire cd.
suid set user id permet à un fichier
exécutable de prendre provisoirement les droits du propriétaire.
C'est utile pour pouvoir écrire un serveur (courrier, forum).
sticky n'est pratiquement plus utilisé. C'est une
optimisation pour ne pas lire trop souvent un fichier exécutable.
static. Les variables externes sont
connues des autres modules quand on fait cc -c xxx.c, cc -c
yyy.c et cc xxx.o yyy.o. La table des symboles namelist
externes (et internes) d'un binaire est obtenue par la commande 
nm -g sur Vax. 
static peuvent être aussi locales. Ce sont
alors des variables rémanentes, dont la valeur reste inchangée quand
on sort du bloc correspondant et on y rerentre. 
xxx.c
static int sp = 0;
static stack[1000];
void push (float x)  {stack[sp++] = x;}
float pop (void)     {return stack[--sp];}
yyy.c.
extern void push (float); extern float pop (void);On peut aussi le mettre dans un ``fichier d'interface''
xxx.h et faire 
#include "xxx.h"
static).
cc la déterminer en fonction du nombre d'éléments
initialisés.
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
char prof[] = "levy";
char prof[] = {'l', 'e ', 'v', 'y', '\0'}'
char *profs[] = {"levy", "ehrlich", "rouaix", 
                 "ruget", "doligez", 
                 NULL};
cc que la
variable est très souvent utilisée. Ne pas trop utiliser.
cc appelait l'éditeur de
lien /bin/ld pour permettre la compilation séparée de
plusieurs modules.
% cc -c xxx.c % cc -c yyy.c % cc xxx.o yyy.o % nm -gn a.out | more
.o sont des binaires relogeables. Il y a
toute l'information pour mettre le binaire à toute adresse.
a.out sont des binaires absolus. Sur ds5000:
00400140 T __start ...et sur Vax:
00000000 T start
cc -r permet de faire un fichier .o à partir de 2
fichiers .o
text le
programme, data les données initialisées, bss les
données non initialisées.
size a.out permet de connaître la taille de ces trois
zones. 
% size /vmunix text data bss dec hex 1150864 122384 486672 1759920 1adab0
bss est mise à zéro. Ne
pas trop utiliser ce fait.
limit en Cshell permet de connaître les tailles maximales
autorisées pour ces valeurs.
% limits datasize 65536 kbytes stacksize 512 kbytes
make donne un ensemble de règles pour reconstruire les
modules d'un programme. (Attention: tabulation n'est pas espace!)
Un tri topologique sur les dates permet de reconstruire le minimum.
DESTDIR= /usr/local/bin
all: xxx zzz
xxx: xxx.o yyy.o
        cc -O -o xxx xxx.o yyy.o
xxx.o: xxx.c
        cc -c xxx.c
yyy.o: yyy.c
        cc -c yyy.c
zzz: zzz.c
        cc -O -o zzz zzz.c
install: all
        cp xxx zzz ${DESTDIR}
clean:
        rm -f xxx zzz xxx.o yyy.o
sccs, rcs, cvs permettent de gérer des numéros de
versions.  Très important pour les gros programmes.
errno est une variable qui a une valeur après tout
appel-système. En Unix, l'appel système retourne une valeur anormale
(-1 ou NULL par exemple), et errno permet d'avoir un diagnostic plus
précis.  Ses valeurs possibles sont définies dans 
/usr/include/errno.h
perror (char *s); permet d'écrire un message standard
(en anglais) avec l'argument s suivi de :
% ps PID TT STAT TIME COMMAND 21908 p0 S 0:01 -tcsh (tcsh) 21918 p0 S 1:23 emacs cours.ftex 22670 p0 R 0:00 ps 21920 p1 I 0:02 -tcsh (tcsh)
% ps aux USER PID %CPU %MEM SZ RSS TT STAT TIME COMMAND figer 27300 2.4 0.4 1074 981 ? S N 31:35 StelBot -n Mag0t_ -u arthus figer 2611 2.3 0.5 1166 1072 ? S N 38:21 StelBot nobody 14461 2.0 0.1 407 149 ? S 0:00 /usr/local/w3/bin/httpd charaya 14421 1.3 0.1 548 223 r4 S 0:00 -tcsh (tcsh) charaya 14413 0.9 0.5 2139 1120 ? S 0:00 xterm -ls charaya 14430 0.9 0.0 129 52 r4 S 0:00 rlogin sil root 14433 0.4 0.0 82 36 ra S 0:00 rlogind potters 14395 0.2 0.1 477 204 r2 S 0:00 elm potters 14378 0.2 0.5 2139 1123 ? S 0:00 xterm -ls potters 14387 0.2 0.1 548 221 r2 I 0:00 -tcsh (tcsh) root 9675 0.1 0.1 374 108 ? S 4:11 /usr/local/w3/bin/httpd volkov 14078 0.1 0.5 2137 1120 ? S 0:00 xterm -ls pelikan 10471 0.1 0.4 1440 798 ? S 0:19 xmailtool brunetoe 12396 0.1 1.0 3161 2107 ? S 0:00 xterm -ls -geometry 85x25+0-0 root 9481 0.1 0.0 168 96 ? S 17:11 /usr/etc/ypserv root 9692 0.1 0.0 6 4 ? S 4:43 /etc/update
TIT .COMPUTER AND JOB-SHOP SCHEDULING THEORY AUT .Coffman, Edward G.. Ed. EDI .WILEY-INTERSCIENCE,NEW YORK DAT .1976
fork() duplique le processus courant, et crée un
processus fils par division cellulaire. fork() répond 0
pour le processus fils et le numéro (unique) du processus pour le
processus père. C'est la seule manière de créer des processus
Unix. Elle est lourde, mais permet de passer toute l'information au
fils (comme en biologie). Tout l'espace text,
data, bss,  stack est copié.
for (i = 0; i < 15; i++)
    if (fork() == 0) {
        printf ("child proc %d = %x\n", i, getpid());
        exit (1);
    }
/* suite du pe `re */
r = wait(&status);
printf ("r = %x, status =%\n", r,  status);
exec permet de remplacer l'image mémoire d'un processus
par celle déduite à partir d'un fichier a.out.
if (fork() == 0) {
    execlp ("xxx", "xxx", "a", "b", (char *) 0);
    fprintf (stderr, "xxx not executed\n");
    exit (2);
    }
fork puis
exec. D'où le nouvel appel système vfork.
exec et avec l'entrée/sortie standard
prédéfinie (à cause de < ou >). Or les file descriptors
traversent exec. D'où
fd1 = open ("fichier1", 1);
fd2 = open ("fichier2", 2);
fd3 = open ("fichier3", 2);
if ((pid = fork()) == 0) {
    close (0); dup (fd1);
    close (1); dup (fd2);
    close (2); dup (fd3);
    execlp ("prog", ...);
    exit (1);
}
dup() duplique le file descriptor sur le premier
disponible. On peut aussi utiliser dup2().
fd1 = open ("/dev/ttÿ, 1);
fd2 = open ("/dev/ttÿ, 2);
fd3 = open ("/dev/ttÿ, 2);
if ((pid = fork()) == 0) {
    close (0); dup (fd1);
    close (1); dup (fd2);
    close (2); dup (fd3);
    execlp ("prog", ...);
    exit (1);
}
FILE *fdopen(int fd, char *mode) int fileno(FILE *fp)
ls et ls -R. On devra parcourir la structure renvoyée par
stat(). (Faire attention aux liens).
grep parallèle, ie faire une commande pgrep [-N] string
[file] où N est le nombre de processus forkés et file un
fichier contenant des noms de fichiers (un par ligne) qu'on obtient en
faisant par exemple find . -type f -print 
La sémantique de  pgrep [-N] string [file] est:
grep string sur chacun des seaux. Remarque: on
peut prendre le grep du système ou écrire un grep perso
trivial sans KMP ou Boyer-Moore avec bêtement strcmp et la
méthode quadratique en string et  input.
pgrep:
kill(p,SIGKILL) pour tuer p.