OS experiment three [process communication]

1. The purpose of the experiment

1. Understand and be familiar with the message communication mechanism , pipeline communication , shared storage area mechanism and information volume mechanism supported by Linux .

2. Master the method of exchanging data between processes using the process communication mechanism (IPC) of the Linux system .

2. Experimental content

1. Process communication

Use the system call pipe() to establish a pipeline: two subprocesses P1 and P2 write a sentence to the pipeline respectively:

Child 1 is sending a message!

Child 2 is sending a message!

The parent process reads the information from the two processes from the pipe and displays it on the screen.

The parent process is required to receive the message sent by the child process P1 first, and then receive the message sent by the child process P2. (You can put yourself to sleep through sleep())

2. Message creation, sending and receiving

(1) Use the system calls msgget(), msgsnd(), msgsrv() and msgctl() to create a program for sending and receiving a message with a length of 1K (such as personal address book information).

(2) Use the system calls shmget(), shmat(), sgmdt(), shmctl() related to the shared memory area to compile a program with the same function as above.

(3) Compare the time of data transmission in the above two message communication mechanisms.

3. Design principles (or schemes) and related algorithms

1. Process communication:

Create a pipe, the child process writes data, and the parent process writes data out. Use the wait() function in the parent process so that the parent process has to wait until the child process finishes executing.

Call pipe() to establish a pipeline, and the two child processes write a sentence to the pipeline respectively, and use the wait() function in the parent process to make the parent process wait for the child process to finish execution, and output the messages from P1 and P2 in turn.

2. Creation, sending and receiving of messages

2.1:

(1) Use a program as an "introduction" to fork() two processes, SERVER and CLIENT, to communicate

(2) The SERVER side establishes a message queue with a Key of 75, waiting for messages from other processes. When a message of type 1 is encountered, it is used as an end signal to cancel the queue and exit the SERVER. After receiving a message, SERVER displays a sentence "(Server) received", and then sends a return message to the CLIENT side, displaying a sentence "(Server) sent".

(3) The client side uses the message queue whose key is 75, sends messages of types from 10 to 1 successively, and then exits. The last message is the end signal required by the SERVER side. CLIENT displays a sentence "(Client) sent" after each message sent, and after accepting the return message from the SERVER side, displays a sentence "(Client) received", and then sends the next message.

(4) The parent process ends after both SERVER and CLIENT exit.

2.2:

(1) In order to facilitate the operation and observation of the results, a program is used as the "introduction", and two sub-processes, SERVER and CLIENT, are fork( ) successively to communicate.

(2) The SERVER side establishes a shared area with a KEY of 75, and sets the first byte to -1. As a sign of data empty. Waiting for messages from other processes. When the value of this byte changes, Indicates that the message has been received and processed. Then its value is set to -1 again. If the value encountered is 0, it is regarded as an end signal, the queue is cancelled, and the SERVER is exited. The SERVER is displayed every time it receives data "(server)received".

(3) The client side establishes a shared area of ​​75. When the first byte obtained by sharing is -1, the server side is idle and can send requests. CLIENT then fills in 9 to 0. During the period, wait for the server side to be idle again. Go After these operations, CLIENT exits. CLIENT displays "(client)sent" after each data sent.

(4) The parent process ends after both SERVER and CLIENT exit.

4. Analysis of results

Topic 1: Pipe() function implements pipeline communication

(1) Enter the source code file placement directory and compile the original file

(2) run

Topic two:

1. Use the system calls msgget(), msgsnd(), msgsrv() and msgctl() to create a program for sending and receiving a message with a length of 1K (such as personal address book information).

(1) Compile

 

(2) run

Whenever the Client sends a message, the server receives the message, and the Client sends the next one. The words "(Client)sent" and "(server)received" alternate on the screen.

2. Use the system calls shmget(), shmat(), sgmdt(), shmctl() related to the shared memory area to compile a program with the same function as above

In the process of running, it is found that every time the client sends data, the server waits for about 0.1 seconds before responding. Similarly, after that, the client needs to wait about 0.1 seconds before sending the next data. When the client side sends data, there is no measure to notify the server side that the data has been sent, which needs to be detected by the client's query. At this time, the client side does not give up control of the system, and still occupies the time slice of the CPU. Only when the system is scheduled, it switches to the server process and then responds.

3. Compare the time of data transmission in the above two message communication mechanisms

When the amount of data is relatively small, the first way to transmit data takes less time than the second way to transmit data.

After the message queue and the shared area are established, the data transmission in the shared area is supported by the system hardware and does not consume extra resources; while the message transmission is controlled and implemented by software, and needs to consume a certain amount of CPU resources. Therefore, the shared area More suitable for frequent and large data transfers.

Five, the source program

 1. pipe.c

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>

int main(){
    int fd[3], pid1, pid2;
    char OutPipe[100], InPipe[100];   //建立管道文件,并将文件描述词通过数组返回
pipe(fd);  //父进程建立管道
    while ((pid1 = fork()) == -1) ;    //创建子进程pid1,直到成功
if (pid1 == 0){
        lockf(fd[1], 1, 0);  //给fd[1]文件上锁 ,实现进程互斥
        sprintf(OutPipe, "Child process 2 is sending a message!");     //格式化字符串
        write(fd[1], OutPipe, 50);
        sleep(1);    //休眠
        lockf(fd[1], 0, 0);    //给fd[1]文件解锁
        exit(0);
    }else{    //执行父进程
        while ((pid2 = fork()) == -1) ;   //创建子进程pid2,直到成功
        if (pid2 == 0){
            lockf(fd[1], 1, 0);
            sprintf(OutPipe, "Child process 1 is sending a message!");  
            write(fd[1], OutPipe, 50);
            sleep(1);
            lockf(fd[1], 0, 0);
            exit(0);   //关闭pid2
        }else{
            read(fd[0], InPipe, 50);
            printf("%s\n", InPipe);
            wait(0);
  //从fd[0]代表的读端 读取50字节 保存在buf缓冲区之后,文件的当前读写指针向后移动50字节
            read(fd[0], InPipe, 50);
            printf("%s\n", InPipe);
            exit(0);   //结束父进程
        }
    }
    return 0;
}

 2.1 MessageOne

#include <stdio.h> 
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#define MSGKEY 75          //定义关键词MEGKEY
struct msgform                //定义消息结构
{
    long mtype;
    char mtexe[1030];         //文本长度
}msg;
int msgqid,i;
 
void CLIENT(){
    int i;
    msgqid=msgget(MSGKEY,0777);    //创建消息队列
    for(i=10;i>=1;i--){
         msg.mtype=i;
         printf("(client)sent\n");
         msgsnd(msgqid,&msg,1024,0);       //发送消息msg入msgid消息队列
    }
    exit(0);
}
 
void SERVER(){ 
  msgqid=msgget(MSGKEY,0777|IPC_CREAT); //创建一个所有用户都可以读、写、执行的队列
 do{
      msgrcv(msgqid,&msg,1030,0,0);    //从队列msgid接受消息msg
      printf("(server)receive\n");
  }while(msg.mtype!=1);             //消息类型为1时,释放队列
      msgctl(msgqid, IPC_RMID,0);      //消除消息队列的标识符
      exit(0);
}
 
int main(){
  if(fork())       //父进程
	  SERVER();
    else           //子进程
	  CLIENT();
    wait(0);
    wait(0);
}

 2.2 MessageTwo

#include<stdlib.h>
#include<unistd.h>
#include<stdio.h>
#include<wait.h>
#include<sys/types.h>
#include<sys/msg.h>
#include<sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY  75                   //定义共享区关键词
int shmid,i;
int *addr;
 
void CLIENT(){    
    int i;    
    shmid=shmget(SHMKEY,1024,0777);    //获取共享区,长度1024,关键词SHMKEY
    addr=shmat(shmid,0,0);                //共享区起始地址为addr    
    for(i=9;i>=0;i--) {        
        while(*addr!= -1);                          
        printf("(client)sent\n");                 //打印(client)sent      
        *addr=i;                             //把i赋给addr  
    }    
    exit(0);
}
 
void SERVER(){     
    shmid=shmget(SHMKEY,1024,0777|IPC_CREAT);    //创建共享区   
    addr=shmat(shmid,0,0);                           //共享区起始地址为addr 
    do {    
        *addr=-1;    
        while(*addr==-1);    
        printf("(server)received\n");               //服务进程使用共享区    
    }
    while(*addr);    
    shmctl(shmid,IPC_RMID,0);    
    exit(0);
    }
 
 int main(){    
    if(fork())
		SERVER();    
    if(fork())
		CLIENT();    
    wait(0);    
    wait(0);
}

Guess you like

Origin blog.csdn.net/qq_45037155/article/details/123977871