Sessió 4 curs programació linux
Sessió 4. Programació en C. 9 de maig del 2008
==================================
$ aptitude install manpages-dev
Funcions del nucli per gestionar els fitxers: int
open, int creat, ssize_t read, ssize_t write, off_t
lseek, int unlink
En Unix, tot són fitxers. Per exemple, si volem llegir
un scanner farem un read, si volem escriure en una
impressora farem un write, i amb el open obrirem (o
associarem) el scanner o la impressora.
Des del campus virtual, baixem el fitxer exemples.tgz,
i el descomprimim a /exemples
$ mkdir exemples
$ mv exemples.tgz exemples/
$ cd exemples0
$ tar zxf exemples.tgz
exemple copia.c
assert.h -> em diu que la constant EXIT_SUCCESS és 0
int main (int argc, char **argv) -> comptador
d'argumens i arguments
en el man em diu, quan vull fer servir una cosa com el
open, quins includes he de fer servir
copia.c necessita com a mínim 3 arguments: el
programa, fitxer origen i fitxer destí
O_WRONLY|O_CREAT|O_TRUNC -> OR bit a bit. Aquestes
constants són potències de 2
|| és un OR entre variables, i | és un or bit a bit
els canals estàndard d'entrada, sortida i error no
necessiten orbrir-se
write(STDERR_FILENO,"fitxer no existent\n",19); ->
envia el missatge d'error al canal estàndard d'error.
Li hem de dir el número de caràcters a enviar.
Per provar el fitxer:
gcc -o copia copia.c -> es crea l'executable copia. El
binari és especificat pel paràmetre -o. Fa el
preprocessat, compilació, ensamblatge, i vinculació
(linkatge).
http://www.snoether.com/doc/gcc.html
arguments de gcc:
http://www.snoether.com/doc/gcc2.html
per crear un fitxer, fer per exemple:
$ cat > fitxer1.txt
vaig escrivint, i per acabar, Ctrl-C
Per executar-lo:
$ ./copia fitxer1.txt fitxer2.txt
Si falla la compilació, no trova els include, instalar
libc6-dev
Si volem estalviar-nos el ./, recordar de fer
PATH = $PATH":." -> afegim el . en el PATH, que
representa el directori actual
0666 -> read, write, no execute (6) per a usuari, grup
i altres
open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0666) -> té 3
arguments, encara que l'especificació de open només en
tenia 2. Això és perquè C és un gamberro, segons el
Josep, que no considera que sigui un bon llenguatge de
programació.
$ gcc copia.c -> sempre crea el fitxer a.out, que és
el binari-executable. Si el que vull és elegir el nom
del binari, faig servir el paràmetre -o: gcc copia.c
-o copia
Exemple de llistes enllaçades que he trobat a
Internet:
http://www.infor.uva.es/~benja/ejercicioC-2.html
- include <sys/types.h>
- include <dirent.h>
- include <unistd.h>
- include <errno.h>
- include <stdio.h>
main (int argc, char *argv[])
{
DIR *pdir;
struct dirent *dp;
/* Comprobación de que se pasa el número
correcto de argumentos */
if (argc != 2) {
printf("Uso: %s nombre_directorio\n",
argv[0]);
exit (1);
}
/* Se abre el directorio */
pdir = opendir(argv[1]);
if (pdir == NULL) {
perror("error en opendir.");
exit(1);
}
/* Lectura adelantada para los elementos del
directorio */
dp = readdir(pdir);
while(dp != NULL) {
printf("%s\n", dp->d_name);
dp = readdir(pdir);
}
/* Ya no hay más ficheros y por lo tanto se
cierra el directorio */
closedir(pdir);
exit(0);
}
=====
Exemple amb senyals (en Bash):
crear el fitxer prova:
function accio1 {
echo "senyal 1 rebut(SIGHUP)"
}
trap accio 1
while true
do
sleep 5
echo "."
done
per executar.lo: chmod +x prova
./prova & -> em diu quin és el número del procés
(6728), i comença a funciona. Cada 5 segons escriu un
'.'
per acabar, s'ha de matar el procés:
kill -1 6728
kill -9 6728
(veure la diferència, repassar!!)
prova2:
function accio1 {
echo "senyal 1 rebut(SIGHUP)"
echo " Tanquem els fitxers si en tenim."
exit
}
trap accio 1
while true
do
sleep 5
echo "."
done
Mirar tot el tema de senyals!!
copsa-ctrlc.c
SIGINT: Ctrl-C
fflush(stdout) -> buida el buffer associat al canal
estàndard de sortida
-> amb CTRL-C no podem aturar el programa. Hem
d'enviar un kill -9 des d'un altre terminal, o tambe
el puc aturar amb Ctrl-Z
usa-alarmes: en compilar-ho surt un warning en el
gets. Ens està avisant de què hi ha problemes de
seguretat en l'ús del gets.
Comunicació entre processos. Programació concurrent
(programació d'una pipe)
fork(), de forquilla. El que fa és crear un procés
idèntic. Hereda tot l'entron del procés que l'està
creant.
Concepte de procés pare i procés fill
Taula de descripció de fitxers. Quan faig un open
fitxer, el que retorna és l'index d'aquesta taula.
En aquesta taula, els 3 primers index estan ocupats
pel stdin (0), stdout (1) i stderr(2). Per tant, quan
faig un open, allò normal és que retorni un '3'.
f1=open("fitxer1", O_RDONLY); -> ocupa la posició 3
f2=open("fitxer1", O_RDONLY); -> ocupa la posició 4
f3=dup(f1); -> duplicar una entrada a la taula.
Duplica en la primera posició que trobi lliure.
-> ocupa la posició 5. Això vol dir que per llegir el
fitxer 1 puc fer servir els descriptors 3 ó 5.
El pipe() crea dos descriptors de fitxers: un per
entrada de fitxer, i un per sortida.
mirar les transparències, i veure com he aconseguit la
connexió del pipe entre el pare i el fill.
Exemple de pipe: ordenació per selecció. (min.c)
és necessari els binaris min (que fa el procés
d'ordenació) i present (que mostra la sortida per
pantalla)
per tal de què funcioni:
$ echo "3 2 1 -1 -1 " | ./min | ./min | ./present
o bé
echo "30 50 12 67 42 -1 -1 -1 -1" | ./min | ./min |
./min | ./min | ./present
el -1 fa de sentinella, que significa que un cop
finalitzat el procés d'ordenació, es va passant el
resultat al final, doncs l'últim procés és l'únic que
té el canal de sortida i pot visualitzar el resultat.
El pare té el stdin, i el fill té el stdout
exemple de pipe: programa tub
al revés que abans, El pare té el stdout, i el fill té
el stdin
./tub /bin/ls /bin/more -> té el mateix efecte que ls
| more
parlo i escolto. Missatges
$ touch recull
Forma d'ús:
en dos terminals, en un executo ./parlo i en l'altre
./escolto
aleshores en un escric una línia, i la veig en l'altre
terminal.
semàfors
POSIX: creació de fils de control
filsuma -> mostra la concurrència en la variable
filsuma2 -> sempre funciona