<<
, 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
.