Title: PRODUCTORCONSUMIDOR BUFFER FINITO
1PRODUCTOR-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
2PRODUCTOR-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)
3PRODUCTOR-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)?
4PRODUCTOR-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
5COLA 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
6PRODUCTOR-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.
7PRODUCTOR-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)
8SINCRONIZACION 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)?
9TAREAS EN JAVA
10TAREAS 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.
11TAREAS 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
12TAREAS 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 ...
13TAREAS 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()
14TAREAS 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.
15TAREAS 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.
16METODOS 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.
17METODOS 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
18METODOS 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
19TAREAS 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
20TAREAS 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()
21TAREAS 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
22TAREAS 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
23SOCKETS
24SOCKETS
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 . . .
25SOCKETS
- 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.
26CREAR 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.
27HERENCIA 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.
28CERRAR 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.
29ESPECIFICANDO 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.
30ESPECIFICANDO 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.
31ESPECIFICANDO 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.
32ENVIANDO 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.
33RECIBIENDO 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.
34SERVIDOR
- 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.
35SERVIDOR
- 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
36SERVIDOR
- 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.
37SERVIDOR
- 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).
38SERVIDOR
- 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.
39UN SERVIDOR SIMPLE(pseudo-codigo)?
socket() bind() listen() accept()? for ()
read() write() close()
40ESTRUCTURAS 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()?
41ESTRUCTURAS 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
42ESTRUCTURAS 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.
43UN 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()
44UN 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()