Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Fernando R. Rannou
Departamento de Ingenieria Informatica
Universidad de Santiago de Chile
Concepto de proceso
De programa a proceso
Considere el siguiente programa en C, hello.c:
#include <stdio.h>
#define N 10
main() {
int i;
for (i=0; i < N; i++)
printf("Hola %d\n", i);
}
hello.s
El preprocesador
El preprocesador de gcc, llamado cpp se encarga de expandir los
#include<> y reemplazar la macros y #define<>, entre otras cosas.
El archivo transformado tiene extension .i
$ cat hello.i
...
typedef long unsigned int size_t;
...
extern int printf (__const char *__restrict __format, ...);
main() {
int i;
for (i=0; i < 10; i++)
printf("Hola %d\n", i);
}
El compilador
EL compilador trasforma el codigo a lenguaje assembler
$ cat hello.s
.file "main.c"
.section .rodata
.LC0:
.string "Hola %d\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl $0, -4(%rbp)
jmp .L2
.L3:
movl
movl
movl
movq
movl
call
addl
$.LC0, %eax
-4(%rbp), %edx
%edx, %esi
%rax, %rdi
$0, %eax
printf
$1, -4(%rbp)
.L2:
El ensamblador
El linkeador
Creacion de procesos
Situaciones tpicas que crean nuevos procesos:
1
Solicitud de un usuario mediante la ejecucion de un comando:
$ ./hello
2
3
4
El PCB de Linux
El descriptor de procesos en Linux es task struct
(include/linux/sched.h). Algunos de los elementos mas
importantes son:
struct task_struct {
volatile long state;
// estado del proceso
long counter;
// Usada junto con prioridad
long priority;
// prioridad
unsigned long blocked; // se
nales mascaradas
struct task_struct *next_task, *prev_task; // punteros, anterior y p
int pid;
// Process ID
struct task_struct *p_opptr, *p_pptr, *p_cptr;
// punteros al padre original, actual
// hijo m
as joven, etc
unsigned short uid,euid,suid,fsuid; // ID usuarios
long utime, stime, cutime, cstime, start_time; // usos de procesador
struct thread_struct tss;
// Thread state stack
struct fs_struct *fs;
// info de sistema de archivos
struct files_struct *files; // info sobre archivos abiertos
struct mm_struct *mm;
// punero a estructura de admin memoria
struct signal_struct *sig; // manejadores de se
nales
};
La lista de descriptores
Datos globales
Heap
Stack usuario
{
back_link,__blh;
esp0;
ss0,__ss0h;
esp1;
ss1,__ss1h;
esp2;
ss2,__ss2h;
__cr3;
eip;
eflags;
eax,ecx,edx,ebx;
esp;
ebp;
esi;
edi;
es, __esh;
cs, __csh;
ss, __ssh;
ds, __dsh;
fs, __fsh;
gs, __gsh;
ldt, __ldth;
trace, bitmap;
io_bitmap[IO_BITMAP_SIZE+1];
Proceso
Su descriptor
Su espacio de direcciones
Su contexto, que generalmente es parte del descriptor
Termino
No corriendo
Corriendo
Time-out
Evento
ocurre
Esperar
evento
Bloqueado
Salir
Modelo de 5 estados
Proceso A
Proceso B
Proceso C
Dispatcher
10
12
14
16
18
Procesos suspendidos
Despachar
Entrar
Nuevo
Termino
No corriendo
Corriendo
Time-out
Activar
Evento
ocurre
Bloqueado
Suspendido
Suspender
Esperar
evento
Salir
Bloqueado/Suspendido:
proceso en memoria
secundaria y esperando
por un evento
Listo/Suspendido:
proceso en memoria
secundaria, pero listo
para ejecucion en
cuanto se cargue en
memoria principal
Suspender
Admitir
Admitir
Despachar
Termino
Activar
Listo/
Suspendido
Corriendo
No corriendo
Suspender
Time-out
Evento
ocurre
Evento
ocurre
Suspender
Bloqueado/
Suspendido
Bloqueado
Activar
Esperar
evento
Salir
Trap: interrupci
on asociada a un error de la ejecucion de la
instrucci
on actual
Interrupci
on: evento externo a la ejecucion del proceso
Interrupci
on del reloj por termino de tiempo
Fallo de memoria. La direcci
on de memoria no se encuentra
actualmente en memoria principal.
Ejecuci
on en el contexto de un proceso usuario
Cada vez que se solicita un servivio al SO, simplemente se realiza un
llamado a una rutina del SO, pero no hay cambio de contexto.
Hay cambio de modo usuario a modo kernel
Un n
umero peque
no de tareas, como por ejemplo cambio de
contexto, pueden ejecutarse fuera del contexto usuario
Basado en procesos
Implementa las tareas del SO como una colecci
on de procesos del
sistema
en sistemas multiprocesadores y multicomputadores, pues
Util
permiten que los servicios prestados por los procesos puedan ser
ejecutados exclusivamante en algunos procesadores y as mejorar
rendimiento.
TASK ZOMBIE
TASK STOPPED
start
TASK RUNNING
(ready)
TASK INTERRUPTIBLE
TASK UNINTERRUPTIBLE
Comando ps
C
odigo
R
S
D
T
Z
l
s
<
N
Estado
Runnable (TASK RUNNING)
Sleeping (TAKS INTERRUPTABLE)
Sleeping (TASK UNINTERRUPTABLE)
Stopped (TASK STOPPED).
Zombie (TASK ZOMBIE).
Multi-thread
Session leader
Alta prioridad
Baja prioridad
Ejemplo 1 de fork()
#include <sys/types.h>
#include <unistd.h>
main()
{
int pid;
if ( (pid = fork()) == -1) {
printf("No se pudo crear hijo\n");
exit(-1);
}
if (pid == 0) { // soy el hijo
printf("Soy el hijo y mi pid = %d\n", getpid());
printf("Hijo: el pid de mi padre es = %d\n", getppid());
exit(0);
}
else { // soy el padre
printf("Soy el padre y mi pid = %d\n", getpid());
printf("Padre: el pid de mi hijo es %d\n", pid);
printf("Padre: el pid de mi padre es %d\n", getppid());
exit(0);
}
}
Ejemplo 2 de fork()
Identificadores
t
t
t
t
t
t
La funcion main()
argc es el n
umero de argumentos en lnea de comandos
*argv[] es el vector de punteros los argumentos de lnea de
comandos Ejemplo:
$ sort -n 100 -o file.txt
argc es 5
La funcion atexit()
Esta funcion le permite al proceso registrar manejadores de salida, es
decir funciones que se ejecutan cuando el proceso termina.
#include <stdlib.h>
int atexit(void (*func)(void));
"HOME=/home/batman"
"PATH=/bin:/usr/bin"
"SHELL=/bin/bash"
"USER=batman"
"PWD=/home/batman/lab1"
NULL
$ cat /proc/self/maps
001c2000-001c3000 r-xp
002b8000-002d1000 r-xp
002d1000-002d2000 r-xp
002d2000-002d3000 rwxp
00c87000-00dc4000 r-xp
00dc4000-00dc6000 r-xp
00dc6000-00dc7000 rwxp
00dc7000-00dca000 rwxp
08048000-0804d000 r-xp
0804d000-0804e000 rw-p
0987f000-098a0000 rw-p
b7db6000-b7fb6000 r--p
b7fb6000-b7fb7000 rw-p
b7fcf000-b7fd0000 rw-p
bfaf8000-bfb0d000 rw-p
$ size /bin/cat
text
data
18431
1036
bss
0
001c2000
00000000
00019000
0001a000
00000000
0013d000
0013f000
00dc7000
00000000
00004000
0987f000
00000000
b7fb6000
b7fcf000
bfaf8000
dec
19467
00:00
08:01
08:01
08:01
08:01
08:01
08:01
00:00
08:01
08:01
00:00
08:01
00:00
00:00
00:00
0
66950
66950
66950
67366
67366
67366
0
7294713
7294713
0
7264522
0
0
0
hex filename
4c0b /bin/cat
[vdso]
/lib/ld-2.5.so
/lib/ld-2.5.so
/lib/ld-2.5.so
/lib/i686/nosegneg/libc-2.5.so
/lib/i686/nosegneg/libc-2.5.so
/lib/i686/nosegneg/libc-2.5.so
/bin/cat
/bin/cat
/usr/lib/locale/locale-archive
[stack]
Familia exec()
Si fork() crea un clon de un proceso, como sera posible crear
procesos hijos totalmente distintos a un padre?
execve() ejecuta un nuevo programa en el proceso que realiza la
invocaci
on
execve() no crea un nuevo proceso, sino que sobre-escribe el
programa actual con uno nuevo
#include <unistd.h>
int execve(const char *filename, char *const argv [], char *const
Familia exec()
Las siguientes funciones son front-ends de execve():
#include <unistd.h>
int
int
int
int
int
Para recordar:
l : lista uno a uno los argumentos
v : entrega un vector con los argumentos
p : usa el PATH definido en el medio ambiente del proceso para
encontrar el ejecutable
e : asigna un environment, es decir medio ambiente
Ejemplo de execve()
#include <sys/types.h>
#include <unistd.h>
main()
{
int pid;
if ( (pid = fork()) == -1) {
printf("No se pudo crear hijo\n");
exit(-1);
}
if (pid == 0) { // soy el hijo
if (execlp("ls", "ls", "/home/rannou", 0) == -1) {
printf("no se pudo hacer exec\n");
exit(-1);
}
printf("bye");
}
// soy el padre
wait(pid);
printf("mi hijo finalizo\n");
exit(0);
}