Title: SEMAFOROS
1SEMAFOROS
2SEMAFOROS
- Las soluciones para el problema de exclusion
mutua (seccion critica) que hemos visto son
dificiles de generalizar para problemas mas
complejos. - Para evitar estas dificultades una nueva
herramienta de sincronizacion, llamada semaforo
fue inventada por Dijkstra (1965). - E.W. Dijkstra,Cooperating Sequential Processes,
Report EWD-123, Technological University,
Eindhoven, the Netherlands (1965)?
3SEMAFOROS
- Un semaforo s es una variable entera que puede
ser accesada solamente a traves de dos
operaciones atomicas (i.e., indivisibles) P y V. - La operacion P(s) es equivalente a while (s
lt 0) s s 1 - La operacion V(s) es equivalente a s s
1
4SEMAFOROS
- Cualquier modificacion al valor del semaforo a
traves de las operaciones P y V se ejecuta
atomicamente (i.e., indivisiblemente). - Esto quiere decir que mientras un proceso
modifica el valor del semaforo, ningun otro
proceso puede simultaneamente modificar el mismo
semaforo. - Si dos procesos ejecutan simultaneamente P(s) (o
V(s)), estas operaciones se ejecutaran
secuencialmente en un orden desconocido y
arbitrario.
5SEMAFOROS
- Los nombres P y V de las operaciones sobre
semaforos vienen del Holandes proberen
(probar) y verhogen (incrementar). - En Ingles muchos autores prefieren usar wait y
signal o send.
6SOLUCIONES EN HARDWARE
- Muchos CPUs tienen instrucciones especiales que
permiten checar y modificar el contenido de una
palabra en memoria o intercambiar el contenido de
dos palabras en memoria, y todo esto en un ciclo
de maquina. - Estas instrucciones especiales se pueden usar
para resolver el problema de la seccion critica. - La caracteristica importante de estas
instrucciones es que se ejecutan atomicamente,
esto es en un ciclo de maquina.
7SOLUCIONES EN HARDWARE
- Test-and-Set test_and_set(target) temp
target target true return temp - Swap swap(a, b) temp a a b b
temp
8SOLUCIONES EN HARDWARE
- Empieza con lock false While(true)
while (test_and_set(lock)
seccion critica lock
false seccion no-critica
9SOLUCIONES EN HARDWARE
- Empieza con lock false aparte cada proceso
tiene una variable local, key while (true)
key true do until swap(lock,
key) until (key false) seccion
critica lock false seccion
no-critica
10lock The lock variable.
1 locked, 0 unlocked. dd
0 spin_lock mov eax, 1 Set
the EAX register to 1. loop xchg eax,
lock Atomically swap the EAX register
with the lock
variable. This will
always store 1 to the lock, leaving
previous value in the EAX
register. test eax, eax Test EAX
with itself. Among other things, this will
set the processor's Zero
Flag if EAX is 0.
If EAX is 0, then the lock was unlocked and
we just locked it.
Otherwise, EAX is 1 and
we didn't acquire the lock.
jnz loop Jump back
to the XCHG instruction if the Zero Flag is
not set, the lock was
locked, and we need to spin. ret
The lock has been acquired, return
to the calling
function. spin_unlock mov eax, 0
Set the EAX register to 0. xchg eax,
lock Atomically swap the EAX register
with the lock
variable. ret The lock
has been released.
11SECCION CRITICASOLUCION CON SEMAFOROS
- Podemos usar semaforos para resolver el problema
de la seccion critica para n procesos, o lo que
es lo mismo, para n tareas. - Los n procesos, o tareas, comparten un semaforo
comun llamado mutex con un valor inicial de 1.
Cada proceso o tarea ejecuta while (true)
P(mutex) seccion critica V(mutex)
seccion no-critica
12SINCRONIZACIONSOLUCION CON SEMAFOROS
- Los semaforos tambien pueden ser usados para
resolver varios problemas de sincronizacion. - Supongamos que tenemos dos tareas. Tarea T1 con
comando S1 y tarea T2 con comando S2 y que se
requiere que el comando S2 de tarea T2 se ejecute
despues de que el comando S1 de tarea T1 ha
terminado.
13SINCRONIZACIONSOLUCION CON SEMAFOROS
- Este esquema se puede implementar dejando que T1
y T2 compartan un semaforo sinc incializado a
0. - Ademas T1 tiene el codigo S1 V(sinc)
- y T2 tiene el codigo P(sinc) S2
14(No Transcript)
15SINCRONIZACIONSOLUCION CON SEMAFOROS
- Semaforos s1, s2, s4, s5, s6 incializados a 0
- Parbegin begin T1V(s1)end begin
T5V(s5)end begin P(s5)T4V(s4)V(s4)end be
gin P(s1)P(s4)T2V(s2)end begin
P(s2)T3end begin P(s4)T6V(s6)end begin
P(s6)T7endparend
16RELACIONES DE PRECEDENCIA DE UN SISTEMA DE TAREAS
- Defina un semaforo sj para cada tarea Tj que no
sea una tarea inicial. - Para cada tarea noinicial hacemos lo
siguiente P(sj) Tj ...seguida por V(sk)
para cada Tk que es un sucesor de Tj - El valor inicial del semaforo sj es -(dj -1),
donde dj es el numero de ancestros inmediatos de
Tj
17TAREA 3
- Ejecute dos tareas (o procesos) independientes
que sumen dos matrices A y B y que presenten el
resultado en una tercera matriz C.. - El programa lo pueden escribir en C, C, o Java
y pueden usar procesos o tareas.
18ROW-MAJOR
- En computacion row-major y column-major son
dos metodos usados para almacenar matrices
multi-dimensionales en memoria lineal. - Siguiendo la practica convencional de notacion de
matrices el primer indice indica la fila y el
segundo indice indica la columna. - En almacenamiento row-major las filas de la
matriz se almacenan una tras la otra otra manera
de ver esto es que el segundo indice varia mas
rapidamente que el primer indice.
19ROW-MAJOR
- Este es el metodo usado en C, C, Java, y muchos
otros lenguajes. - Excepto en FORTRAN, MATLAB, y LabVIEW. Estos usan
column-major. - Considere la siguiente 2x3 matrix 1 2 3 4 5 6
- Esta matriz se declara en C o C como int A
1,2,3, 4,5,6 - Y se almacena en memoria como 1 2 3 4 5 6
20ROW-MAJOR
- El offset de una columna a la siguiente es 1 y
de una fila a la siguiente es 3. - El offset lineal desde el principio del arreglo
a cualquier elemento Aij es offset i
columnas jdonde columnas es el numero de
columnas del arreglo. Por ejemplo el elemento
A12, el cual es 6, esta en la posicion 1 3
2 5
21ROW-MAJOR
- Aparte del detalle trivial de que en C escribimos
Aij en lugar de Ai,j, esta tecnica se
generaliza de una manera sencilla a mas de dos
dimensiones. - Por ejemplo, un arreglo de 2x2x2 se puede
declarar como int A222 1,2,
3,4, 5,6, 7,8 - Otra manera de pensar acerca de esto es que un
arreglo en C es en realidad un arreglo de una
dimension donde cada elemento es a su vez un
arreglo.
22/ Two independent tasks that add two matrices
A and B and put the result in C. One task adds
the first half of A and B, while the second
task adds the other half of A and B. Halves
could be by rows or by columns here we do it
by rows / include ltstdio.hgt include
ltpthread.hgt void add(void arg) static int
A3 1,2,3, 4,5,6 static int B3
6,5,4, 3,2,1 static int
C23 static int row0 0 static int row1
1 int main() int i, j pthread_t
t0 / t0 thread / pthread_t t1
/ t1 thread / / Create threads t0 and t1
/ pthread_create(t0, NULL, add, row0)
pthread_create(t1, NULL, add, row1) /
join threads / pthread_join(t0, NULL)
pthread_join(t1, NULL) for (i 0 i lt 2
i) for (j 0 j lt 3 j)?
printf("d ", Cij)
printf("\n") return 0
23void add(void arg) int i ((int
)arg) / fixed row / int j
for (j 0 j lt 3 j)? Cij
Aij Bij
24COLA DE ESPERA CIRCULAR SINCRONIZADAQUEUE
- Tenemos dos apuntadores uno al frente de la cola
y otro al final de la cola. - Suponemos que la cola es un arreglo de n
elementos cola0, cola1,...,colan-1 y que
inicialmente frente final 0. - INSERTAR x al final de la cola final (final
1) n if (final frente) error
overflow else colafinal x - REMOVER x del frente de la cola if (frente
final) error underflow else frente
(frente1)n x colafrente
25COLA DE ESPERA CIRCULAR NO SINCRONIZADAQUEUE
- Tenemos dos apuntadores uno al frente de la cola
y otro al final de la cola. - Suponemos que la cola es un arreglo de n
elementos cola0, cola1,...,colan-1 y que
inicialmente frente final 0. - INSERTAR x al final de la cola colafinal
x final (final 1) n - REMOVER x del frente de la cola x
colafrente frente (frente1) n
26final
frente
27POSIX MUTEXES EN C
- Se usan para resolver el problema de la seccion
critica. - Un mutex se declara e inicializa de la siguiente
manera pthread_mutex_t mutex pthread_mutex
_init(mutex, NULL) - La seccion critica se encuentra entre una llamada
a pthread_mutex_lock(mutex) y pthread_mutex_unlock
(mutex). - Ver paginas man.
28POSIX SEMAFOROS EN C(COUNTING SEMAPHORES)?
- Estos semaforos pueden incrementarse sin limite,
pero se decrementan solamente hasta cero. - Estos semaforos se declaran e inicializan
como sem_t sem sem_init(sem, TRUE,
10)este semaforo es inicializado a 10 y se
comparte entre procesos. - sem_post() (V()) incrementa el semaforo, y
sem_wait() ( P()) lo decrementa si su valor es
mayor que cero, de otra manera bloquea el proceso
o tarea que lo llamo.
29PRODUCTOR-CONSUMIDOR
30PRODUCTOR-CONSUMIDOR
- Consideremos dos tareas en donde una es el
productor y la otra el consumidor. - El productor es una tarea ciclica y cada vez que
completa un ciclo produce informacion que tiene
que ser procesada por el consumidor. - El consumidor tambien es una tarea ciclica y cada
vez que completa un ciclo procesa la ultima
informacion producida por el consumidor.
31PRODUCTOR-CONSUMIDORBUFFER INFINITO
- La relacion entre el productor y el consumidor es
la de transmision de informacion en un solo
sentido a traves de un canal de comunicacion. - Como una primera aproximacion a una solucion
suponemos que las dos tareas se comunican a
traves de un buffer con capacidad ilimitada
esto es, las porciones de informacion producidas
no se necesitan consumir inmediatamente sino que
pueden ser almacenadas en el buffer infinito.
32CONSUMIDOR
PRODUCTOR
Buffer con capacidad ilimitada
33PRODUCTOR-CONSUMIDORBUFFER INFINITO
- La suposicion, no muy real, de que el buffer es
ilimitado no nos debe de preocupar mucho en este
punto en la busqueda de una solucion. - La solucion que buscamos es asimetrica en el
sentido de que el productor puede adelantarse de
una manera ilimitada respecto al consumidor, sin
embargo, el consumidor nunca puede ir adelante
del productor. - El productor nunca tiene que esperar.
- Si el buffer esta vacio, el consumidor debe
esperar.
34PRODUCTOR-CONSUMIDORBUFFER INFINITO(Inicialmente
llenos 0)?
- PRODUCTORfor() produce(info) inserta(in
fo) V(llenos)
- CONSUMIDORfor() P(llenos) remueve(info)
consume(info)
35PRODUCTOR-CONSUMIDORBUFFER INFINITO
- La primera linea del productor, produce(info),
representa la parte del codigo en el cual se
genera la siguiente porcion de informacion. - Que es la informacion? Esto depende del
problema. Puede ser un bit, todo un archivo, una
imagen, etc. - Cuando la primera linea ha terminado, ya se ha
generado la informacion. - La segunda linea, inserta(info), representa el
codigo que coloca la informacion en el buffer.
Despues de su ejecucion la informacion ha sido
insertada completamente en el buffer, pero el
consumidor todavia no lo sabe.
36PRODUCTOR-CONSUMIDORBUFFER INFINITO
- La operacion V(llenos) confirma la presencia de
informacion en el buffer, esto es señala, al
consumidor la presencia de una o mas porciones de
informacion en el buffer. - Note que es absolutamente indispensable que la
operacion V(llenos) sea precedida por la adicion
completa de la informacion en el buffer en otras
palabras, es indispensable que la operacion
V(llenos) sea la ultima del productor. - Tambien es indispensable que la operacion
P(llenos) sea la primera del consumidor. - El resto del consumidor es facil de entender.
37CONSUMIDOR
PRODUCTOR
BUFFER FINITO
38PRODUCTOR-CONSUMIDORBUFFER FINITO
- La solucion con un buffer infinito no es real.
- Esta es una solucion con una relacion asimetrica
en el sentido de que el productor puede avanzar a
cualquier velocidad sin ningun obstaculo, sin
embargo, el consumidor nunca puede ir adelante
del productor. - La relacion se vuelve simetrica cuando los dos se
comunican a traves de un buffer finito de tamaño
n. - En este caso, el consumidor produce espacios
vacios, y el productor consume espacios vacios.
39PRODUCTOR-CONSUMIDORBUFFER FINITO
- Para la solucion simetrica tenemos dos semaforos
llenos y vacios. - El semaforo llenos tiene el valor inicial 0 y su
valor en cualquier instante es el numero de
elementos que se encuentran en la cola de espera
(i.e., buffer)? - El semaforo vacios tiene el valor inicial n y su
valor en cualquier instante es el numero de
posiciones vacias en la cola de espera (i.e.,
buffer).
40PRODUCTOR-CONSUMIDORBUFFER FINITO(Incialmente
llenos 0, vacios n)?
- CONSUMIDORfor() P(llenos) remueve(info
) V(vacios) consume(info)
- PRODUCTORfor() produce(info) P(vacios)
inserta(info) V(llenos)
41PRODUCTOR-CONSUMIDORBUFFER FINITO(Incialmente
llenos 0, vacios n)?
- CONSUMIDORfor() sem_wait(llenos) remue
ve(info) sem_post(vacios) consume(info)
- PRODUCTORfor() produce(info) sem_wait(v
acios) inserta(info) sem_post(llenos)
42PRODUCTOR-CONSUMIDORBUFFER FINITO
- Indicamos como nP(s) el numero de operaciones P
sobre el semaforo s y similarmente como nV(s) el
numero de operaciones V sobre el semaforo s. - Si k es el valor inicial de un semaforo s,
entonces tenemos el siguiente invariante sobre el
semaforo s nP(s) lt V(s) k - Por invariante queremos decir que el semaforo
satisface siempre esta relacion.
43PRODUCTOR-CONSUMIDORBUFFER FINITO
- En el caso del productor-consumidor tenemos los
siguientes invariantes nP(llenos) lt
V(llenos) nP(vacios) lt V(vacios) n - Es claro que un ciclo del consumidor solo puede
comenzar cuando llenos es mayor que 0 en la
operacion P(llenos). Debido a que V(llenos)
aumenta llenos por 1 y P(llenos) lo disminuye
por 1, es claro que en cualquier secuencia de
ejecucion valida el numero de ciclos completos
del consumidor no puede exceder los ciclos del
productor.
44PRODUCTOR-CONSUMIDORBUFFER FINITO
- Similarmente, es claro que un ciclo del productor
solo puede comenzar cuando vacios es mayor que
0 en la operacion P(vacios). Debido a que
V(vacios) aumenta vacios por 1 y P(vacios) lo
disminuye por 1, es claro que en cualquier
secuencia de ejecucion valida el numero de ciclos
completos del productor no puede exceder los del
consumidor por mas de n.
45PRODUCTOR-CONSUMIDORBUFFER FINITO
- Supongamos que el buffer esta lleno. En este caso
tenemos que nP(vacios) V(vacios) nEs
decir, el productor produjo n porciones de
informacion mas de las que el consumidor consumio
hasta ese momento. - Esto implica que el productor debe estar
bloqueado en P(vacios) ya que de otra manera se
violaria el invariante y resultaria ennP(vacios)
gt V(vacios) n
46PRODUCTOR-CONSUMIDORBUFFER FINITO(Incialmente
llenos 0, vacios n)?
- CONSUMIDORfor() sem_wait(llenos) remue
ve(info) sem_post(vacios) consume(info)
- PRODUCTORfor() produce(info) sem_wait(v
acios) inserta(info) sem_post(llenos)
47PRODUCTOR-CONSUMIDORBUFFER FINITO
- Supongamos que el buffer esta vacio. En este caso
tenemos que nP(llenos) V(llenos) Es
decir, el consumidor consumio todo lo que el
productor produjo hasta ese momento. - Esto implica que si el consumidor quiere consumir
otra porcion de informacione antes que el
productor produzca otra, el consumidor se
bloqueara en P(llenos) ya que de otra manera se
violaria el invariante y resultaria ennP(llenos)
gt V(llenos)?
48PRODUCTOR-CONSUMIDORBUFFER FINITO
- Supongamos que el buffer esta lleno. En este caso
tenemos que nP(vacios) V(vacios) n Es
decir, el productor lleno todos los espacios
vacios desocupados por el consumidor mas lo n
espacios vacios originales. - Esto implica que si el productor quiere llenar
otro espacio antes que el consumodir desocupe
uno, el productor se bloqueara en P(vacios) ya
que de otra manera se violaria el invariante y
resultaria en nP(vacios) gt V(vacios) n
49COLA DE ESPERA CIRCULAR NO SINCRONIZADAQUEUE
- Tenemos dos apuntadores uno al frente de la cola
y otro al final de la cola. - Suponemos que la cola es un arreglo de n
elementos cola0, cola1,...,colan-1 y que
inicialmente frente final 0. - INSERTAR x al final de la cola colafinal
x final (final 1) n - REMOVER x del frente de la cola x
colafrente frente (frente1) n
50PRODUCTOR-CONSUMIDORBUFFER FINITO
- Lo unico que queda por demonstrar es que el
productor y el consumidor no accesan a la misma
vez la misma posicion (casilla) en la cola. - La unica situacion el la que lproductor y
consumidor, pueden accesar simultaneamente la
misma posicion en la cola es cuando los
apuntadores frente y 'final son iguales. - Frente es igual a final solamente en dos
ocasiones cuando la cola esta llena y cuando la
cola esta vacia. Sin embargo en el primer caso el
productor se bloquea y en el segundo caso el
consumidor se bloque. Por lo tanto ninguno de los
dos accesa nunca la misma posicion en la cola.
51PRODUCTOR-CONSUMIDORBUFFER FINITO(mutex 1,
llenos 0, vacios n)?
- CONSUMIDORfor() sem_wait(llenos) sem_w
ait(mutex) remueve(info) sem_wait(mutex)
sem_post(vacios) consume(info)
- PRODUCTORfor() produce(info) sem_wait(v
acios) sem_wait(mutex) inserta(info) sem_
post(mutex) sem_post(llenos)
52SINCRONIZACION CON BANDERAS
- La tarea que espera a una bandera de
sincronizacion es la tarea que debe de quitar
(clear) la bandera. - Una bandera no se debe de levantar (set) hasta
no esta seguro de que ha sido bajada (clear). - La primera parte arriba asegura que una bandera
no se baja (clear) antes de que se haya
levantado (set)? - La segunda parte arriba asegura que ninguna otra
tarea levante otra vez la bandera (set) antes
de que haya sido bajada (clear)?
53TAREAS EN JAVA
54TAREAS EN JAVA
- Para crear una tarea se crea un objeto
Thread Thread tarea new Thread() - Despues de que un objeto Thread ha sido creado se
puede configurar y ejecutar. Configurarlo
significa darle prioridad, nombre, etc. - Cuando la tarea esta lista para correr, se
arranca llamando al metodo start. - El metodo start crea una nueva tarea.
55TAREAS EN JAVA
class PingPong extends Thread String
word // word to print int delay
// how long to pause PingPong(String
whatToSay, int delayTime) word
whatToSay delay delayTime
public void run()
try for ()
System.out.print(word
" ")
sleep(delay)
catch(InterruptedException e)
return // end this thread
public static
void main(String args) new
PingPong("ping", 33).start() // 1/30 second
new PingPong(PONG, 100).start() // 1/10
second
56TAREAS EN JAVA
ping PONG ping ping ping PONG ping ping ping PONG
ping ping ping PONG ping ping ping PONG ping ping
ping PONG ping ping ping PONG ping ping ping PONG
ping ping ping PONG ping ping ping PONG ping ping
ping PONG ping ping ping PONG ping ping ping PONG
ping ping ping PONG ping ping ping PONG ping ping
ping PONG ping ping ping PONG ping ping ping PONG
ping ping ping PONG ping ping ping PONG ping ping
ping PONG ping ping ping PONG ping ping ping PONG
ping ping ping PONG ping ping ping PONG ping ping
ping PONG ping ping ping PONG ping ping ping PONG
ping ping ping PONG ping ping ping PONG ping ping
ping PONG ping ping ping PONG ping ping ping PONG
ping ping ping PONG ping ping ping ping PONG ping
ping ping PONG ping ping ping PONG ping ping ping
PONG ping ping ping PONG ping ping ping PONG ping
ping ping PONG ping ping ping PONG ping ping ping
PONG ping ping ping PONG ping ping ping PONG ping
ping ping PONG ping ping ping PONG ping ping ping
PONG ping ping ping PONG ping ping ping PONG ping
ping ...
57TAREAS EN JAVA
class PingPong implements Runnable
String word // word to print int delay
// how long to pause
PingPong(String whatToSay, int delayTime)
word whatToSay delay
delayTime public void run()
try
for ()
System.out.print(word " ")
Thread.sleep(delay)
catch(InterruptedExcept
ion e) return
// end this thread
public static void main(String args)
Runnable ping new PingPong("ping",
33)? Runnable pong new PingPong(PONG,
100)? new Thread(ping).start() new
Thread(pong).start()
58TAREAS EN JAVA
- Un objeto que es Runnable puede ser ejecutado
como una tarea pasandolo al constructor de
Thread. - Debido a que Java es single-inheritance es
imposible heredar de una clase y ser Thread a la
misma vez.
59TAREAS EN JAVA
- Hay dos clases de tareas en Java user y
daemon. - Mientras exista una tarea user, la aplicacion
continua ejecutandose. - Cuando la utlima tarea user termina, cualquier
tarea daemon que exista tambien se termina. - Cuando el metodo main crea una nueva tarea,
esta tarea hereda el tipo user de la tarea
original. - No hay nada especial acerca la tarea original, es
solamente la primera tarea que empezo. - Una aplicacion continua corriendo hasta que todas
las tareas tipo user han terminado.
60METODOS SINCRONIZADOS
- Si una tarea invoca un metodo sincronizado de un
object, es objeto es locked (candado). - Cualquier otra tarea que invoque cualquier metodo
sincronizado sobre el mismo objecto, sera
bloqueda hasta que el candado se abra. - La sincronizacion obliga que la ejecucion de dos
tareas se excluyan mutuamente en el tiempo.
61METODOS SINCRONIZADOS
class Account private double
balance public Account(double initialDeposit)
balance initialDeposit public
synchronized double getBalance() return
balance public synchronized void
deposit(double amount) balance
amount
62METODOS SINCRONIZADOS
El metodo sincronizado tiene dos partes un
objeto que se bloquea y comandos que se ejecutan
cuando se obtiene el candado. La forma general
del comando es synchronized(expr)? comando
La expresion entre parentesis debe dar como
resultado un objecto. Cuando se obtiene el
candado el comando se ejecuta como si fuera un
metodo sincronizado sobre ese objeto. / Hacer
todos los elementos del arreglo no-negativos
/ Public static void abs(int values)
synchronized (values) for (int i 0 i
lt values.length i) if (valuesi) lt
0)? valuesi -valuesi
63TAREAS EN JAVA
- wait y notify son metodos definidos en la
clase Object y son heredados por todas las
clases. - Una de las caracteristicas mas importantes de
wait es que la suspension de la tarea y la
liberacion del candado ocurren atomicamente. - Cuando la tarea se despierta, despues de haber
sido notificada, vuelve a adquirir el candado
64TAREAS EN JAVA
- Cuando una tarea espera por un evento
particular, dicha tarea espera a que otra tarea
le avise (notify) de ese evento particular. - Normalmente, la tarea que espera un aviso hace
algo como synchronized void doWhenCondition()
while (!condition) wait() //
continuar aqui La condicion se debe de
checar en un loop. - Por otro lado, las tareas que modifican la
condicion hacen algo como synchronized void
changeCondition() // cambiar la
condicion notify()
65TAREAS EN JAVA
- Muchas tareas pueden estar esperando sobre el
mismo objeto. - notify() avisa a solo una de las tareas que estan
esperando. - notifyAll() le avisa a todas las tareas que estan
esperando por una cierta condicion. - Estos metodos deben de ser invocados solo dentro
de codigo que ha sido sincronizadodirecta o
indirrectamente. - Llamando a estos metodos desde codigo no
sincronizado genera la excepcion
IllegalMonitorStateException
66TAREAS EN JAVA
class Queue Element head, tail public
synchronized void insert(Element p) if (tail
null)? head p else tail.next
p p.next null tail p notify()
public synchronized Element remove() try
while (head null)? wait() catch
(InterruptedException e) return
null Element p head // remember
first head head.next if (head
null)? tail null return p
67SOCKETS
68SOCKETS
telnet movil.citedi.mx 80 Trying
200.38.6.141... Connected to movil.citedi.mx. Esca
pe character is ''. GET / HTTP/1.0 HTTP/1.1
200 OK Date Wed, 15 Oct 2008 204512
GMT Server Apache/2.2.0 (Fedora)? Last-Modified
Sun, 26 Aug 2007 021759 GMT ETag
"586ff-1271-43890d94d23c0" Accept-Ranges
bytes Content-Length 4721 Connection
close Content-Type text/html charsetUTF-8 lt!DO
CTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http//www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"gt lth
tml xmlns"http//www.w3.org/1999/xhtml"
xmllang"en" gt ltheadgt lttitlegt movil.citedi.mx
lt/titlegt ltscript language"JavaScript"gt var
width screen.width . . .
69SOCKETS
- La base para comunicacion en red en Linux es el
socket - Los sockets se comportan parecido a los archivos
o perifericos en Linux. - Esto quiere decir que una vez que un programa
abre un socket y crea un canal de comunicacion
TCP/IP, el programa puede usar las llamadas
tradicionales al sistema read y write para
mandar y leer datos a traves del canal.
70CREAR SOCKETS
- La llamada al sistema socket crear un
socket sock socket(pf, type, protocol)? - Toma tres argumentos y regresa un socket
descriptor. - pf especifica la familia del protocolo (e.g.,
PF_INET). - type especifica el tipo de comunicacion deseado
(e.g., SOCK_STREAM, SOCK_DGRAM, SOCK_RAW). - Protocol especifica el protocolo.
71HERENCIA DE SOCKETS
- Linux usa las llamadas al sistema fork y exec
para empezar nuevos procesos. - Este es un proceso de dos pasos en el primer
paso fork crea una copia del proceso padre en el
segundo paso exec reemplaza el codigo del
proceso. - El nuevo proceso hijo hereda todos los sockets
abiertos del proceso padre (lo mismo para los
archivos). - Todos los procesos tienen los mismos derechos
sobre el socket. - El sistema operativo mantiene la cuenta de
cuantos procesos estan usando un socket.
72CERRAR SOCKETS
- La llamada al sistema close cierra el
socket close(sock)? - El argument sock especifica el descriptor del
socket que se va a cerrar. - Cuando un proceso termina, por cualquier razon,
el sistema operativo cierra los sockets que el
proceso tenia abiertos. - Internamente una llamada a close decrementa la
cuenta y destruye el socket cuando la cuenta
llega a cero.
73ESPECIFICANDO UNA DIRECCION LOCAL
- Inicialmente el socket se crea sin ninguna
asociacion a ninguna direccion. - Una vez que el socket ha sido creado, usamos la
llamada al sistema bind para asociar una
direccion local con el socket, de la siguiente
manera bind (socket, localaddr, addrlen)? - Socket es el descriptor del socket localaddr es
una estructura (sockaddr) que especifica la
direccion local con la cual el socket estara
asociado y addrlen es el tamano de la direccion
en bytes.
74ESPECIFICANDO UNA DIRECCION REMOTA
- Inicialmente el socket es creado en un estado
desconectado, lo cual significa que el socket no
esta asociado con ninguna direccion remota. - El programa debe de hacer la llamada al
sistema connect(socket, destaddr, addrlen)? - Socket es el descriptor del socket destaddr es
una estructura (sockaddr) que especifica la
direccion remota con la cual el socket estara
asociado y addrlen es el tamano de la direccion
en bytes.
75ESPECIFICANDO UNA DIRECCION REMOTA
- El comportamiento de connect depende del
protocolo que se seleccione. En el caso tipico de
la familia PF_INET el sistema construye una
coneccion TCP con la dircecion remota y da un
error si no puede hacerlo.
76ENVIANDO DATOS
- write(socket, buffer, length)?
- Socket es el descriptor del socket a donde se va
a escribir. - Buffer es la direccion de los datos que se van a
enviar - Length es el numero de bytes para enviar.
77RECIBIENDO DATOS
- read(socket, buffer, length)?
- Socket es el descriptor del socket de donde se va
a leer. - Buffer es la direccion donde se van a almacenar
los datos que se van a recibir. - Length es el numero de bytes para leer.
78SERVIDOR
- El servidor crea un socket, lo asocia con un
puerto (binds it) y espera por peticiones de
clientes. - La llamada al sistema listen prepara el socket
para recibir conecciones con clientes listen(s
ocket, queuelen)? - socket es el descriptor del socket.
- queuelen es el largo de la cola de espera para
el socket.
79SERVIDOR
- El servidor usa las llamadas al sistema socket,
bind y listen, crear el socket, asociarlo con un
puerto conocido, y poner el sockect en estado
pasivo para esperar conecciones. - Para aceptar conecciones, el socket usa la
llamada al sistema accept. Una llamada a accept
hace que el servidor sea bloqueado hasta que
reciba una peticion de conneccion por alguna
cliente newsock accept(socket, addr,
addrlen)addr es una estructura de tipo sockaddr
80SERVIDOR
- Cuando una peticion para coneccion llega, el
sistema llena addr con la direccion del cliente
que hizo la peticion y pone en addrlen el tamano
de la direccion. Finalmente, el sistema crea un
nuevo socket que tiene su direccion remota
apuntando a la del cliente que hizo la peticion,
y regresa al cliente el descriptor del nuevo
socket. - Cuando una peticion para coneccion llega, accept
regresa (i.e., se desbloquea) y el servidor
atiende la peticion.
81SERVIDOR
- El servidor puede atender las peticiones
iterativamente o concurrentemente. - En el modo iterativo el mismo servidor atiende la
peticion, cierra el nuevo socket creado para esta
peticion y llama a accept para atender nuevas
peticiones. - En el modo concurrente el servidor crea un
proceso esclavo (it forks a child process to
handle the request).
82SERVIDOR
- Debido a que el proceso esclavo hereda el nuevo
socket, este puede atender a la peticion y darle
servicio al cliente. - Cuando termina el proceso esclavo cierra el
socket. - Despues de arrancar el proceso esclavo, el
servidor original cierra su copia del nuevo
socket y regresa a aceptar nuevas conecciones.
83UN SERVIDOR SIMPLE(pseudo-codigo)?
socket() bind() listen() accept()? for ()
read() write() close()
84ESTRUCTURAS PARADIRECCIONES
// IPv4 AF_INET sockets struct sockaddr
u_char sa_len // total length u_short sa_fa
mily // type of address char sa_date14 //
value of address struct sockaddr_in
u_char sin_len // total length
u_short sin_family // e.g. AF_INET,
AF_INET6 un_short sin_port //
e.g. htons(3490)? struct in_addr sin_addr
// IP address char
sin_zero8 // unused (set to
zero)? struct in_addr unsigned long
s_addr // load with inet_pton()?
85ESTRUCTURAS PARADIRECCIONES
- La estructura mas general es sockaddr.
- Esta contiene un identificador de familia de dos
bytes y un arreglo de 14 bytes para la direccion. - Esta direccion no es lo suficientemente grande
para contener las direcciones de todas las
familias. - Hay familias que tienen direcciones mas grandes
de 14 bytes. - Sin embargo debido q a que las direcciones de la
familia AF_INET caben en sockaddr esta sigue
siendo usada
86ESTRUCTURAS PARADIRECCIONES IP
- La estructura sockaddr_in contiene un
identificador de familia de 2 bytes, un numero de
puerto de 2 bytes, una direccion IP de 4 bytes y
8 bytes que no son usados. - El identificador de familia es AF_INET para el
protocolo TCP/IP. - La direccion IP se carga con la funcion inet_pton
esta fucion extiende la funcion inet_addr la cual
se usaba anteriormente. - Una aplicacion que usa TCP/IP puede usar
sockaddr_in exclusivamente y no necesita usar
sockaddr.
87UN CLIENTE SIMPLE(pseudo-codigo)?
El cliente crea un socket, llama a connect para
conectarse con el servidor e interacciona con el
servidor escribiendole y recibiendo la respuesta.
Cuando termina cierra la coneccion. socket() conn
ect() for () write() read() close()
88UN SERVIDOR SIMPLE(pseudo-codigo)?
El servidor corre para siempre. Espera por una
nueva coneccion en un determinado puerto accepta
la coneccion interacciona con el cliente y
cierra la coneccion. socket() bind() listen()
for () accept() write() read() close()