Operating System – Experiment 2: Process Communication (Pipelines and Shared Memory)

Operating system experiment report

Experiment 2: Process Communication (1) – Pipes and Shared Memory

1. Purpose of the experiment

  1. Be familiar with and master the pipeline mechanism and implement inter-process communication;
  2. Be familiar with and master the shared memory mechanism and implement inter-process communication.

2. Experimental content and steps

2.1 Task 1

  1. Read the above example of parent-child processes using pipes to communicate (Example 1), write out the program running results and analyze them.
  2. Write a program: the parent process uses a pipe to hand a string to the child process for processing. The child process reads the string, reverses the characters in it, and then hands it to the parent process. The parent process finally reads and prints the reversed string.

2.2 Task 2

  1. Read the program in Example 2, run the program once, and then use the ipcs command to check the status of the shared storage area in the system, execute the program again, and then use ipcs Use the command to check the status of shared memory in the system, compare the two results, and analyze the reasons. Finally, use the ipcrm command to delete the shared storage area you created.
  2. Log in to two windows, first run Example 3 program 1 in one window (or log in to only one window, first run in the background in that window Program 1), and then run Example 3, Program 2 in another window, observe and analyze the running results of the program. After running, you can use ctrl + c to end the running of program 1.
  3. Write a program: Use the system calls shmget(), shmat(), shmdt(), shmctl() to compile the program. It is required to generate a 30-byte long private shared memory segment in the parent process. Next, set a character pointer pointing to the shared memory segment and write a string of uppercase letters to the storage area pointed to by the pointer. Call fork() to generate a child process and let the child process display the contents of the shared memory segment. Next, the uppercase letters are changed to lowercase, and the child process modifies the contents of the shared memory. Afterwards, the child process will detach the shared memory segment and exit. After the parent process sleeps for 5 seconds, the contents of the shared memory segment are displayed here (already in lowercase letters at this time).

3. Code and operation result analysis

3.1 Task 1(2)

3.1.1 Code

b1e2a403cc604ef487131fff848dd4db.png

3.1.2 Operation results

55b3825e342a45edac11dd6217a88afc.png

3.1.3 Result Analysis

2f9f0a34bf904106bd4cf0a5aa0c082d.png

fcbc9727f44b48369222e5cdfe7ce08d.png

Summary: A simple pipeline can be created using the system call pipe(fd). Among them, fd[0] stores the file descriptor (pipe exit) used by the reading process, and fd[1] stores the file descriptor (pipe entry) used by the writing process. First, the parent process is executed, but it is temporarily blocked because there is no content in the pipe; then the child process is executed, sending a message to the parent process, that is, writing data in the pipe, and then closing the child process; then there is data in the pipe, and the parent process continues execution. Receive pipe messages and print output.

3.2 Task 1(2)

3.2.1 Code

#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
    int x, fd1[2], fd2[2]; //fd1 parent process writes, fd2 child process writes
    char buf[30], s[30], temp;
    char c;
    pipe(fd1);
    pipe(fd2); //Create two pipes
    printf( "Please enter a string\\
" );
    scanf("%s", buf);
    while((x=fork()) == -1 );

    //Execute child process
    if(x == 0) {
        close(fd1[1]); //Close the parent process for writing
        close(fd2[0]); //Close the child process for reading, let the child process write and the parent process read
        printf( "child process!\\
" );
        read(fd1[0], s, 30);
        printf( "Get string from parent process: %s\\
", s);
        //Reverse the string
        for(int i = 0; i <= strlen(s)/2; i + + ){
            temp = s[i];
            s[i] = s[strlen(s) - i - 1];
            s[strlen(s) - i - 1] = temp;
        }
        write(fd2[1], s, 30);
        exit(0);
    } else {
        //Execute the parent process
        close(fd1[0]); //Close the parent process for reading
        close(fd2[1]); //Close the child process for reading, let the child process write and the parent process read
        printf( "parent process! \\
");
        write(fd1[1], buf, 30);
        wait(NULL);
        read(fd2[0], buf, 30);
        printf( "Get the reverse string from the subprocess: %s\\
" , buf);
    }
}

3.2.2 Operation results

9be1e7e3fe2b4c31802401e722334de4.png

3.2.3 Result Analysis

6ead233c8eaf419dae7a9ea5307714fc.png

3.3 Task 2(1)

3.3.1 Code

4e7f93bcbbb14fc4b5bcf807d2e01450.png

3.3.2 Operation results

9e0c070138cf4540a007aae73ec12798.png

Execute and use the ipcs command for the first time

a88998185dae4ef1bb33425dd838f4a3.png

Execute and use the ipcs command a second time

680c33cd70a840fd913324a9101c6e91.png

Use the ipcrm command to delete the created share zone

3.3.3 Result Analysis

  1. Specify the shared area code 004;
  2. Define shmid_1 and shmid_2 as descriptors after receiving the shared zone;
  3. Under shared area 004, create a shared area with a length of 1000 with 0644 as the permission value. If it fails, an error will be reported;
  4. Print out the descriptor 54 of the first shared section;
  5. Under shared area 004, create a shared area with a length of 20 again with 0644 as the permission value. If it fails, an error will be reported;
  6. Print out the descriptor 55 of the second shared section;
  7. Use the ipcs command to view the storage situation. You can see that the key values of the two shared sections are 0x00000004 and 0x00000000. The owner is rql and the permissions are 644, the number of connection shared areas are 1000 and 20 respectively;
  8. Execute the program again and check that the two shared section descriptors printed out are 54 and 56;
  9. Use the ipcs command to view the storage situation. You can see that the key values of the two shared sections are 0x00000004 and 0x00000000. The owner is rql and the permissions are 644, and the number of connection shared areas are 1000 and 20 respectively.
  10. Use the ipcrm -M 004 command to delete the created shared zone based on keywords.
  11. Use the ipcs command to check the storage situation. There is no shared area with the key value 0x00000004, and the deletion was successful.

Comparison of the results of the two runs: The first shared identifier after the two runs is the same, and the second shared identifier is different.

Cause analysis: When creating the first shared area, shmflag is “permission value|IPC_CREAT”. If the key value is new (the first time the program is executed), it will be returned The newly created memory segment identifier; if the key value is old (second execution of the program), the memory segment identifier with the same key value that already exists in the kernel is returned, so both output 54, that is, the same shared area segment . The second return value is different. The reason is that when calling the shmget method, the key value is set to IPC_PRIVATE, which will generate a new shared memory segment. Therefore, the two return value outputs are 55 and 56 respectively, that is, two different shared areas. part.

3.4 Task 2(2)

3.4.1 Code

881ad9e373ed4b85b02fbc205073bce2.png

Example 3-Program 1

4d1a85e894234d26bbbcffb6a942f8c1.png

Example 3-Program 2

3.4.2 Operation results

Log in to two windows, first run Example 3 program 1 in one window, the result is as shown below:

4b09199373634886b889ac508da9e24f.png

Example 3-Program 1 running results

Then run Example 3 Program 2 in another window, the result is as shown below:

c22f4bb1f436400d889a15d72145a7f2.png 4b17996f086b434192e801ab8b73b59e.png

Example 3-Program 2 running results

3.4.3 Result Analysis strong>

  1. In program section 1, specify the shared area code SHMKEY as 004, the macro definition constant K as 1024; define the i variable, pointer pint (int type) and address pointer addr (char type).
  2. Introducing the cleanup() function, which implements the following functions: deletes the memory segment pointed to by shmid, but does not actually delete it, only the memory segment currently connected to it The actual deletion operation will not occur until the last process correctly disconnects from it.
  3. The for loop implements signal semaphore interruption.
  4. Under the shared area SHMKEY, create a shared area with a length of 16K with 0777 as the permission value, and return the identifier to shmid;
  5. The process mounts the memory segment, and the system obtains the first address of the shared area and assigns it to addr, and maps it to its own memory space;
  6. The first address number printed out is “0x4d599000”;
  7. Convert the local pointer addr to the int pointer type and assign it to pint. At this time, pint points to the first address of the shared area;
  8. Through the for loop, write the i variable from 0 to 255 one by one to the shared area pointed to by pint. Each time a piece of data is written, the address is shifted backwards. once.
  9. The pause() function waits for the process to read, and the terminal is paused and occupied, that is, another terminal is opened at this time (program 2 is executed).
  10. In program section 2, under the shared area SHMKEY, create a shared area with a length of 8K with 0777 as the permission value, and return the identifier to shmid ;
  11. The process mounts the memory segment, and the system obtains the first address of the shared area and assigns it to addr, and maps it to its own memory space;
  12. Convert the local pointer addr to the int pointer type and assign it to pint. At this time, there is another pint pointing to the first address of the shared area (similar to the above pint is different);
  13. Access the contents of the shared area starting from the first address through a for loop. Each time a piece of data is read, the address pointer is shifted backward by one bit, and the result is output as a program segment. 1 writes 0, 1, 2, …, 255;
  14. After the execution of program section 2 is completed, use ctrl + c to end the execution of program section 1.

3.5 Task 2(3)

3.5.1 Code

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 004 //The last three digits of the student number
#define K 1024
int pshmid; //parent
int cshmid; //childint
int main() {
    int i, *pint, x;
    int delete;
    char *paddr, *caddr, *paddr2, c;
    char words[26]= {'A','B','C','D','E','F','G',\ 'H','I','J',
                     'K','L','M','N','O','P','Q','R',' S',
                     'T','U','V','W','X','Y','Z'};
    while((x = fork()) == -1 );
    if(x == 0) {
        printf("Subprocess!\\
");
        cshmid = shmget(SHMKEY, 30*K, 0666);//The child process creates a 30 shared area
        caddr = shmat(cshmid, 0, 0); //Hook to get the first address of the shared area
        for(i = 0; i <= 25; i + + ) {
            printf( "%c ", *caddr); //Read data
            *caddr = (*caddr + 'a'-'A'); //Get lowercase
            caddr + + ;
            if(i==25)
                printf( "\\
");
        }
        delete = shmdt(caddr); //release
        exit(0);
    }else {
        printf( "parent process!\\
" );
        pshmid = shmget(SHMKEY, 30*K, 0666| IPC_CREAT); //Create a 30K share area
        paddr = shmat(pshmid, 0, 0); //Hook to get the first address of the shared area
        paddr2 = paddr; //Hook to read lowercase
        for(i = 0; i <= 25; i + + ) {
            *paddr + + = words[i]; //Write uppercase letters to the shared area
        }
        sleep(5);
        for(i = 0; i <= 25; i + + ){
            printf( "%c ", *paddr2 + + ); //Read data
            if(i==25)
                printf( "\\
" );
        }
    }
    return 0;
}

3.5.2 Operation results strong>

b10dde95014b4a2b88235044bf693510.png

3.5.< strong>3 ResultsAnalysis

92e012e0c1d14fa0a5eafaa53737a440.png

4. Experimental experience

This is the second in-class experiment on the operating system. It mainly uses program analysis and code design and writing to familiarize yourself with the two new process communication mechanisms of pipes and shared memory to achieve inter-process communication.

At the beginning of the experiment, I first read and studied the knowledge points in the ppt, mastered the usage of pipe(), read(), and write() functions in the pipeline mechanism, and understood the shmget() and shmat() in the shared memory mechanism. ), shmdt(), and shmctl() functions to prepare for subsequent experiments.

For task one (1), analyze the results after running the code given in ppt. At first, I mistakenly applied the knowledge of process concurrency, thinking that the system executes the parent process first. When the parent process reads the empty string, the system concurrent execution switches to the child process, and then passes the data into the pipe, and then lets the parent process print the output. Although this analysis is consistent with the results of the operation, the internal principle is actually completely wrong. Later, I realized my problem. The correct analysis should be that the parent process was called first, but because there was no data in the pipe, the child process was called only when the parent process was blocked, instead of the system switching to the child process concurrently. This not only gave me a deeper understanding of system concurrency, but also taught me that processes without data in the pipeline will be blocked.

For task one (2), write code to implement two-way communication in which the parent process passes data to the child process, and the child process modifies it and then passes it back to the parent process. After analysis, I used the case in Example 1 as a template to create two pipelines to complete data transmission through the read() and write() functions. The difficulty here is to distinguish clearly which ports are not used and need to be closed().

In task two (1), I have a deeper understanding of the shmget() function. If the first parameter of this function is IPC_PRIATE, it will create a new shared memory segment. If it is a custom key, it will create a new one, and if it exists, it will be used; the second parameter is the length; the third parameter is Permissions. If you want to use the same shared area together, you must ensure that the permissions are consistent. If it is the permission value | IPC_CREAT, it is different from IPC_PRIVATE. It will determine whether there is an old one in the memory. If there is an old one, continue to use it. If not, a new one will be created. Shared memory area, so the two results of ipcs are different.

In task two (2), I learned how to access the shared memory area for read and write operations. Since there is no parent-child process, the pause function is used for multi-terminal testing. This question also uses the shmctl() and shmat() functions. The return value of shmat is the first address of the shared area given by the system, so you need to be proficient in pointer operations.

Task 2 (3) is an improvement on the above topic, adding a shared memory mechanism to process concurrency. I create the shared area in the parent process and write uppercase letters. Then, due to concurrency, I need to give the sleep function and let the system call the child process to read the data from the shared area and convert it to lowercase, overwriting the original content.

This experiment was successfully completed. After analysis and practice, I learned from these five contents: process concurrency and blocking, use of pipe function, understanding of shmget parameters, shmctl and shmat, multi-terminal operations, addresses Benefit a lot from the understanding of pointers and code writing.

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. CS entry skill treeLinux introductionFirst introduction to Linux37787 people are learning the system