Experiment 2: process communication (I) -- pipeline and shared memory
1, Experimental purpose
1. Be familiar with and master the pipeline mechanism and realize inter process communication
2. Be familiar with and master the mechanism of shared memory, and realize inter process communication
2, Experiment contents and steps
1. Task 1
(1) Read the above example of parent-child process communicating through pipeline (example 1), write the running results of the program and analyze them.
(2) Programming: the parent process uses a pipeline to give a string to the child process for processing. The child process reads the string, reverses the characters inside, and then gives them to the parent process. The parent process finally reads and prints the reverse string.
2. Task 2
(1) Read the program of example 2, run the program once, then use the ipcs command to view the shared memory in the system, execute the program again, and then use the ipcs command to view the shared memory in the system, compare the results of the two times, and analyze the reasons. Finally, use the ipcrm command to delete the shared storage area established by yourself.
(2) Each student logs in two windows, first run example 3 program 1 in one window (or log in only one window, first run program 1 in the background mode in this window), and then run example 3 program 2 in another window to observe and analyze the running results of the program. After running, you can use ctrl+c to end the running of program 1.
(3) Programming: use the system call shmget(), shmat(), shmdt(), shmctl() to program. A 30 byte private shared memory segment is required to be generated in the parent process. Next, set a character pointer 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 that displays the contents of the shared memory segment. Next, the upper case letter is changed to lower case, and the child process modifies the contents of the shared memory. After that, the child process will disconnect the shared memory segment and exit. After sleeping for 5 seconds, the parent process displays the contents of the shared memory segment here (which is already lowercase at this time)-
3, Code and running result analysis
1. Task 1
Example 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) Read the above example of parent-child process communicating through pipeline (example 1), write the running results of the program and analyze them.
Operation results:
analysis:
Use the system call pipe() to create a simple pipe. fd[0] stores the file descriptor (pipeline exit) for the read process, and fd[1] stores the file descriptor (pipeline entry) for the write process. First run the parent process, then close the parent process, the child process starts and sends messages to the parent process, and then close the child process. The parent process receives messages and prints them out.
(2) Programming: the parent process uses a pipeline to give a string to the child process for processing. The child process reads the string, reverses the characters inside, and then gives them to the parent process. The parent process finally reads and prints the reverse string.
The preparation procedure is as follows:
#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); } }
Operation results:
analysis:
Call pipe(fd); After creating a pipeline, call the fork() function to generate two processes. First, execute the sub process, close the pipeline exit, and write content to the pipeline through the pipeline entrance. In the parent process, the pipeline entry is closed, the content written before is read from the pipeline through the pipeline exit, and finally output.
2. Task 2
(1) Read the program of example 2, run the program once, then use the ipcs command to view the shared memory in the system, execute the program again, and then use the ipcs command to view the shared memory in the system, compare the results of the two times, and analyze the reasons. Finally, use the ipcrm command to delete the shared storage area established by yourself.
Example 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); }
Operation results:
Run the program for the first time, and then use the ipcs command to view the shared storage area in the system. The results are as follows:
Run the program for the second time, and then use the ipcs command to view the shared storage area in the system. The results are as follows:
analysis:
shmget() is to create a new shared area or return an existing shared area descriptor; int shmgetkey_t key, int size, int shmflag), where key is the shared area code specified by the user, size is the length of the shared storage area, and shmflag is used to identify the creation condition machine and access permission of the shared memory segment. If successful, the identifier of the shared memory segment is returned, which is used to uniquely identify an object in the kernel. For each shared memory segment existing in the kernel storage space, the kernel maintains a data structure shmid for it_ ds; If it fails, return - 1 and set errno.
The second shared identifier after two runs is different. Therefore, when viewing with ipcs, the keywords, shared memory identifiers, access permissions, bytes, etc. in the shared memory segment are different.
(2) Each student logs in two windows, first run example 3 program 1 in one window (or log in only one window, first run program 1 in the background mode in this window), and then run example 3 program 2 in another window to observe and analyze the running results of the program. After running, you can use ctrl+c to end the running of program 1.
Example 3 (procedure 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); /*Establish a 16K shared area SHMKEY */ addr = shmat(shmid, 0, 0);/*Hook up and get the first address of the shared area */ printf("addr 0x%s\n", addr); pint = (int*)addr; for (i = 0; i < 256; i++) *pint++ = i; pause();/*Waiting for the receiving process to read */ }
Example 3 (procedure 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);/*Get the id of the shared area SHMKEY */ addr=(char *)shmat(shmid,0,0);/*Connection share*/ pint=(int *)addr; for (i=0;i<256;i++) printf("%d\n",*pint++);/*Print content in the share*/ return 0; }
Experimental results:
analysis:
First, the system calls shmctl to delete the memory segment pointed to by the predefined shmid. Then, the system calls shmget to create a 161024 byte shared memory segment, and successfully returns the identifier of the shared memory segment to shmid. Then, the system calls shmat again to connect the memory segment, and returns that the shared memory segment is connected to the address addr in the address space of the calling process.
When program 1 runs, the program starts to execute. The system calls shmget to create a 81024 byte shared memory segment, then calls shmat to hook up the memory segment, the system selects the hook up address, and finally outputs the converted hook up address. Finally, the contents of the first 255 are output. The shared memory mechanism only provides the operating conditions for the communication process to access the shared memory, while the synchronization control of communication depends on the semaphore mechanism.
(3) Programming: use the system call shmget(), shmat(), shmdt(), shmctl() to program. A 30 byte private shared memory segment is required to be generated in the parent process. Next, set a character pointer 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 that displays the contents of the shared memory segment. Next, the upper case letter is changed to lower case, and the child process modifies the contents of the shared memory. After that, the child process will disconnect the shared memory segment and exit. After sleeping for 5 seconds, the parent process displays the contents of the shared memory segment here (which is already lowercase at this time)
The preparation procedure is as follows:
#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); /*Establish a 16K shared area SHMKEY */ addr_1=shmat(shmid_1,0,0);/*Hook up and get the first address of the shared area*/ 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); /*Establish a 16K shared area SHMKEY */ addr_2=shmat(shmid_2,0,0);/*Hook up and get the first address of the shared area*/ 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; }
Experimental results: