Experimento de sistema operativo 2: comunicación de procesos (tuberías y memoria compartida)

Experimento 2: Comunicación de procesos (1) - Tuberías y memoria compartida

1. El propósito del experimento

1. Familiarizarse y dominar el mecanismo de canalización y realizar la comunicación entre procesos
2. Familiarizarse y dominar el mecanismo de memoria compartida y realizar la comunicación entre procesos

2. Contenido y pasos del experimento

1. Tarea 1
(1) Lea el ejemplo anterior de comunicación entre los procesos padre e hijo usando conductos (Ejemplo 1), escriba el resultado de ejecución del programa y analícelo.
(2) Escribir un programa: el proceso principal usa una canalización para entregar una cadena al proceso secundario para su procesamiento. El proceso hijo lee la cadena, invierte los caracteres que contiene y luego se los pasa al proceso padre, y el proceso padre finalmente lee e imprime la cadena invertida.
2. Tarea 2
(1) Lea el programa en el Ejemplo 2, ejecute el programa una vez y luego use el comando ipcs para verificar el estado de la memoria compartida en el sistema, ejecute el programa nuevamente y luego use el comando ipcs para verificar el estado de la memoria compartida en el sistema Compare los resultados y analice las razones. Finalmente, use el comando ipcrm para eliminar el área de almacenamiento compartido creada por usted mismo.
(2) Cada estudiante inicia sesión en dos ventanas, primero ejecuta el programa 1 del ejemplo 3 en una ventana (o solo inicia sesión en una ventana, primero ejecuta el programa 1 en segundo plano en esta ventana) y luego ejecuta el ejemplo 3 en otra ventana Programa 2, observe y analice los resultados de ejecución del programa. Después de ejecutar, puede usar ctrl+c para finalizar la ejecución del programa 1.
(3) Escriba un programa: utilice las llamadas del sistema shmget(), shmat(), shmdt(), shmctl() para programar. Requiere que se genere un segmento de memoria compartida privada de 30 bytes de longitud en el proceso principal. A continuación, establezca un puntero de carácter en el segmento de memoria compartida y escriba una cadena de letras mayúsculas en el área de memoria a la que apunta el puntero. Llama a fork() para generar un proceso secundario y deja que el proceso secundario muestre el contenido del segmento de memoria compartida. A continuación, las letras mayúsculas se cambian a minúsculas y el proceso hijo modifica el contenido de la memoria compartida. Después de eso, el proceso secundario separará el segmento de memoria compartida y saldrá. Después de que el proceso principal duerme durante 5 segundos, el contenido del segmento de memoria compartida se muestra aquí (ya está en minúsculas en este momento). -

3. Análisis de código y ejecución de resultados

1. Tarea 1

Ejemplo 1:

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include <sys/wait.h>
int main()
{
    
       int x,fd[2];
    char buf[30],s[30];
    pipe(fd);
    while ((x=fork())==-1);
    if (x==0)
    {
    
    
       close(fd[0]);
       printf("Child Process!\n");
       strcpy(buf,"This is an example\n");
       write(fd[1],buf,30);
       exit(0);
    }
    else{
    
    
       close(fd[1]);
       printf("Parent Process!\n");
       read(fd[0],s,30);
       printf("%s\n",s);
   }
   return 0;
}

(1) Lea el ejemplo anterior de comunicación entre los procesos padre e hijo usando conductos (Ejemplo 1), escriba y analice los resultados de ejecución del programa.
resultado de la operación:
inserte la descripción de la imagen aquí

Análisis:
use la llamada al sistema pipe() para crear una tubería simple. fd[0] almacena el descriptor de archivo (salida de conducto) utilizado por el proceso de lectura, y fd[1] almacena el descriptor de archivo (entrada de conducto) utilizado por el proceso de escritura. Primero ejecute el proceso principal, luego cierre el proceso principal, el proceso secundario se inicia, envía un mensaje al proceso principal, luego cierra el proceso secundario, el proceso principal recibe el mensaje e imprime la salida.
(2) Escribir un programa: el proceso principal usa una canalización para entregar una cadena al proceso secundario para su procesamiento. El proceso hijo lee la cadena, invierte los caracteres que contiene y luego se los pasa al proceso padre, y el proceso padre finalmente lee e imprime la cadena invertida.
Escriba el programa de la siguiente manera:

#include<stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
    
    
        int x,count,left,right,temp,fd[2],fe[2];
        char c,buf[30],s[30];
        pipe(fd);
        pipe(fe);
        printf("please input a line of char:\n");
        scanf("%s",buf);
        while((x=fork())==-1);
        if(x==0){
    
    
                close(fd[0]);
                close(fe[1]);
                printf("Child Process!\n");
                write(fd[1],buf,30);
                read(fe[0],buf,30);
                printf("%s\n",buf);
                exit(0);
        }else{
    
    
                close(fd[1]);
                close(fe[0]);
                count=0;
                do{
    
    
                        read(fd[0],&c,1);
                        s[count++]=c;
                }while(c!='\0');
                printf("Parent Process!\n");
                printf("%s\n",s);count-=2;
                for(left=0,right=count;left<=count/2;left++,right--){
    
    
                        temp=s[left];
                        s[left]=s[right];
                        s[right]=temp;
                }
                write(fe[1],s,30);
                wait(0);
        }
}

resultado de la operación:
inserte la descripción de la imagen aquí

analizar:

Call pipe(fd); Después de crear una tubería, llame a la función fork() para generar dos procesos, primero comience a ejecutar el proceso secundario, cierre la salida de la tubería y escriba contenido en la tubería a través de la entrada de la tubería. En el proceso principal, la entrada de la tubería se cierra, el contenido previamente escrito se lee desde la tubería a través del extremo de salida de la tubería y, finalmente, se genera la salida.

2. Tarea 2

(1) Lea el programa en el Ejemplo 2, ejecute el programa una vez, luego use el comando ipcs para verificar el estado de la memoria compartida en el sistema, ejecute el programa nuevamente y luego use el comando ipcs para verificar el estado de la memoria compartida. memoria en el sistema, y ​​realice los dos resultados, compare y analice las razones. Finalmente, use el comando ipcrm para eliminar el área de almacenamiento compartido creada por usted mismo.
Ejemplo 2:

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main()
{
    
    
	key_t key=15;
	int shmid_1,shmid_2;
	if ((shmid_1=shmget(key,1000,0644|IPC_CREAT))==-1){
    
    
        perror("shmget shmid_1");exit(1);
	}
	printf("First shared memory identifier is %d\n",shmid_1);
	if ((shmid_2=shmget(IPC_PRIVATE,20,0644))==-1){
    
    
        perror("shmget shmid_2");exit(2);
	}
	printf("Second shared memory identifier is %d\n",shmid_2);
	exit(0);
}

Resultado de la ejecución:
ejecute el programa por primera vez y luego use el comando ipcs para verificar el estado del área de almacenamiento compartido en el sistema. Los resultados son los siguientes:

Ejecute el programa por segunda vez y luego use el comando ipcs para ver el estado del área de almacenamiento compartido en el sistema. Los resultados son los siguientes:
inserte la descripción de la imagen aquí

Análisis:
shmget() es para crear una nueva área compartida o devolver un descriptor de área de memoria compartida existente; int shmgetkey_t key, int size, int shmflag), donde key es el número de área compartida especificado por el usuario, y size es la memoria compartida area La longitud de shmflag se utiliza para identificar la condición de creación de la máquina y el permiso de acceso del segmento de memoria compartida. Si tiene éxito, se devuelve el identificador del segmento de memoria compartida, que se utiliza para identificar de forma única un objeto en el kernel. Para cada segmento de memoria compartida que existe en el espacio de almacenamiento del núcleo, el núcleo mantiene una estructura de datos shmid_ds para él; si falla, devuelve -1 y establece errno.
El segundo identificador compartido al final de las dos ejecuciones no es el mismo. Por lo tanto, cuando se visualiza con ipcs, las palabras clave, los identificadores de memoria compartida, los derechos de acceso, los bytes, etc. en el segmento de memoria compartida son diferentes.

(2) Cada estudiante inicia sesión en dos ventanas, primero ejecuta el programa 1 del ejemplo 3 en una ventana (o solo inicia sesión en una ventana, primero ejecuta el programa 1 en segundo plano en esta ventana) y luego ejecuta el ejemplo 3 en otra ventana Programa 2, observe y analice los resultados de ejecución del programa. Después de ejecutar, puede usar ctrl+c para finalizar la ejecución del programa 1.

Ejemplo 3 (Programa 1)

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define SHMKEY 75
#define K  1024
int shmid;
void cleanup()
{
    
    
shmctl(shmid,IPC_RMID,0);
exit(0);
 }

int main()
{
    
    
        int i, * pint;
        char* addr;
        for (i = 0; i < 20; i++) signal(i, cleanup);
        shmid = shmget(SHMKEY, 16 * K, 0777 | IPC_CREAT); /*建立16K共享区SHMKEY */
        addr = shmat(shmid, 0, 0);/*挂接,并得到共享区首地址 */
        printf("addr 0x%s\n", addr);
        pint = (int*)addr;
        for (i = 0; i < 256; i++) *pint++ = i;
        pause();/*等待接收进程读 */
}

Ejemplo 3 (Programa 2)

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 75  
#define K  1024
int shmid;
int main (){
    
    
        int i,*pint;
        char *addr;
        shmid=shmget(SHMKEY,8*K,0777);/*取共享区SHMKEY的id */
        addr=(char *)shmat(shmid,0,0);/*连接共享区*/
        pint=(int *)addr;
        for (i=0;i<256;i++)
        printf("%d\n",*pint++);/*打印共享区中的内容*/
        return 0;
}

Resultados experimentales:
inserte la descripción de la imagen aquí

Análisis:
primero, el sistema elimina el segmento de memoria al que apunta el shmid predefinido llamando a shmctl, luego el sistema llama a shmget para crear un segmento de memoria compartida de 16 1024 bytes y devuelve con éxito el identificador del segmento de memoria compartida a shmid, y luego, el sistema vuelve a llamar shmat conecta el segmento de memoria y devuelve la dirección addr donde el segmento de memoria compartida está conectado al espacio de direcciones del proceso de llamada.
Cuando se ejecuta el programa 1, el programa comienza a ejecutarse, el sistema llama a shmget para crear un
segmento de memoria compartida de 8 1024 bytes y luego llama a shmat para montar el segmento de memoria, el sistema selecciona la dirección de montaje y finalmente genera la dirección de montaje convertida . Finalmente salida el contenido de los primeros 255. El mecanismo del área de memoria compartida solo proporciona las condiciones operativas para que el proceso de comunicación acceda al área de memoria compartida, y el control de sincronización de la comunicación solo puede completarse confiando en el mecanismo de semáforo.

(3) Escriba un programa: utilice las llamadas del sistema shmget(), shmat(), shmdt(), shmctl() para programar. Requiere que se genere un segmento de memoria compartida privada de 30 bytes de longitud en el proceso principal. A continuación, establezca un puntero de carácter en el segmento de memoria compartida y escriba una cadena de letras mayúsculas en el área de memoria a la que apunta el puntero. Llama a fork() para generar un proceso secundario y deja que el proceso secundario muestre el contenido del segmento de memoria compartida. A continuación, las letras mayúsculas se cambian a minúsculas y el proceso hijo modifica el contenido de la memoria compartida. Después de eso, el proceso secundario separará el segmento de memoria compartida y saldrá. Después de que el proceso principal duerme durante 5 segundos, el contenido en el segmento de memoria compartida (ya está en minúsculas en este momento) se muestra aquí.
Escriba el programa de la siguiente manera:

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 200
#define K 1024
int shmid_1,shmid_2;
int main ()
{
    
    
    int x,y,i,*pint;
    char *addr_1,*addr_2;
    char words[5]={
    
    'A','B','C','D','E'};
    shmid_1=shmget(SHMKEY,30*K,0777|IPC_CREAT); /*建立16K共享区SHMKEY */
    addr_1=shmat(shmid_1,0,0);/*挂接,并得到共享区首地址*/
    pint=(int *)addr_1;
    printf ("addr_1 0x%x\n",addr_1);
    for (i=0;i<5;i++) {
    
    
            *pint=words[i];
            pint++;
    }
    while((x=fork())==-1);
    if(x==0){
    
    
        shmid_2=shmget(SHMKEY,30*K,0777|IPC_CREAT); /*建立16K共享区SHMKEY */
        addr_2=shmat(shmid_2,0,0);/*挂接,并得到共享区首地址*/
        pint=(int *)addr_2;
        for(i=0;i<5;i++){
    
    
            printf("%c ",*pint);
            *pint=*pint+32;
            pint++;
    	}
        printf("\n");
        y=shmdt(addr_2);
        exit(0);
    }else{
    
    
        sleep(5);
        pint=(int *)addr_1;
        for(i=0;i<5;i++){
    
    
            printf("%c ",*pint);
            pint++;
        }
        printf("\n");
    }
    return 0; 
}

Resultados experimentales:
inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/david2000999/article/details/122504414
Recomendado
Clasificación