In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
This article is about what the five modes of communication between processes are. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.
There are five ways of communication between processes: 1, pipeline, slow speed, limited capacity, only father and son processes can communicate; 2, FIFO, any process can communicate, but the speed is slow; 3, message queue, capacity is limited by the system; 4, semaphores, can not transmit complex messages, can only be used for synchronization; 5, shared memory area.
Five ways to communicate between processes:
I. Pipeline
Pipes, usually unnamed pipes, are the oldest form of UNIX system IPC.
1. Features:
It is half-duplex (that is, data can only flow in one direction) and has a fixed reader and writer.
It can only be used for communication between related processes (also between parent-child or sibling processes).
It can be regarded as a special file, and ordinary read, write and other functions can also be used for its reading and writing. But it is not an ordinary file, does not belong to any other file system, and exists only in memory.
I. Pipeline
Pipes, usually unnamed pipes, are the oldest form of UNIX system IPC.
1. Features:
It is half-duplex (that is, data can only flow in one direction) and has a fixed reader and writer.
It can only be used for communication between related processes (also between parent-child or sibling processes).
It can be regarded as a special file, and ordinary read, write and other functions can also be used for its reading and writing. But it is not an ordinary file, does not belong to any other file system, and exists only in memory.
2. Prototype: 1 # include 2 int pipe (int fd [2]); / / return value: if 0 is returned for success,-1 for failure
When a pipe is established, it creates two file descriptors: fd [0] opens for reading and fd [1] opens for writing. As shown below:
To close the pipe, simply close these two file descriptors.
3. Examples
Pipes in a single process are of little use. So, usually the process that calls pipe then calls fork, which creates an IPC channel between the parent process and the child process. As shown in the following figure:
If you want the data flow to flow from the parent process to the child process, close the read side of the parent process (fd [0]) and the write end of the child process (fd [1]); otherwise, you can flow the data flow from the child process to the parent process.
1 # include 2 # include 3 4 int main () 5 {6 int fd [2]; / / two file descriptors 7 pid_t pid; 8 char buff [20]; 9 10 if (pipe (fd)
< 0) // 创建管道11 printf("Create Pipe Error!\n");12 13 if((pid = fork()) < 0) // 创建子进程14 printf("Fork Error!\n");15 else if(pid >) / / parent process 16 {17 close (fd [0]); / / close reader 18 write (fd [1], "hello world\ n", 12); 19} 20 else21 {22 close (fd [1]); / / close writer 23 read (fd [0], buff, 20); 24 printf ("% s", buff); 25} 26 27 return 0 28} II. FIFO
FIFO, also known as named pipes, is a file type.
1. Characteristics
FIFO can exchange data between unrelated processes, unlike unnamed pipes.
FIFO has a pathname associated with it, and it exists in the file system as a special device file.
2. Prototype 1 # include 2 / / return value: 0 for success and-13 int mkfifo for error (const char * pathname, mode_t mode)
Where the mode parameter is the same as the mode in the open function. Once you have created a FIFO, you can manipulate it with the normal file Imax O function.
When open a FIFO, the difference between whether to set the non-blocking flag (O_NONBLOCK):
If O_NONBLOCK is not specified (the default), the read-only open blocks to some other process and opens the FIFO for writing. Similarly, write-only open blocks to some other process and opens it for reading.
If O_NONBLOCK is specified, the read-only open returns immediately. Writing only open will error return-1 if no process has opened the FIFO for reading, its errno is set to ENXIO.
3. Examples
FIFO communicates in a way similar to using files to transfer data in a process, except that FIFO-type files also have the characteristics of pipes. When the data is read out, the data is cleared in the FIFO pipeline at the same time, and "first-in, first-out". The following example demonstrates the process of using FIFO for IPC:
Write_fifo.c
1 # include 2 # include / / exit 3 # include / / O_WRONLY 4 # include 5 # include / / time 67 int main () 8 {9 int fd;10 int n, I int fd;10 int 11 char buf [1024]; 12 time_t tp;13 14 printf ("I am% d process.\ n", getpid ()); / / explain the process ID15 16 if ((fd = open ("fifo1", O_WRONLY))
< 0) // 以写打开一个FIFO 17 {18 perror("Open FIFO Failed");19 exit(1);20 }21 22 for(i=0; i 0) // 读取FIFO管道23 printf("Read message: %s", buf);24 25 close(fd); // 关闭FIFO文件26 return 0;27 } 在两个终端里用 gcc 分别编译运行上面两个文件,可以看到输出结果如下: 1 [cheesezh@localhost]$ ./write_fifo 2 I am 5954 process. 3 Send message: Process 5954's time is Mon Apr 20 12:37:28 2015 4 Send message: Process 5954's time is Mon Apr 20 12:37:29 2015 5 Send message: Process 5954's time is Mon Apr 20 12:37:30 2015 6 Send message: Process 5954's time is Mon Apr 20 12:37:31 2015 7 Send message: Process 5954's time is Mon Apr 20 12:37:32 2015 8 Send message: Process 5954's time is Mon Apr 20 12:37:33 2015 9 Send message: Process 5954's time is Mon Apr 20 12:37:34 201510 Send message: Process 5954's time is Mon Apr 20 12:37:35 201511 Send message: Process 5954's time is Mon Apr 20 12:37:36 201512 Send message: Process 5954's time is Mon Apr 20 12:37:37 2015 1 [cheesezh@localhost]$ ./read_fifo 2 Read message: Process 5954's time is Mon Apr 20 12:37:28 2015 3 Read message: Process 5954's time is Mon Apr 20 12:37:29 2015 4 Read message: Process 5954's time is Mon Apr 20 12:37:30 2015 5 Read message: Process 5954's time is Mon Apr 20 12:37:31 2015 6 Read message: Process 5954's time is Mon Apr 20 12:37:32 2015 7 Read message: Process 5954's time is Mon Apr 20 12:37:33 2015 8 Read message: Process 5954's time is Mon Apr 20 12:37:34 2015 9 Read message: Process 5954's time is Mon Apr 20 12:37:35 201510 Read message: Process 5954's time is Mon Apr 20 12:37:36 201511 Read message: Process 5954's time is Mon Apr 20 12:37:37 2015 上述例子可以扩展成 客户进程-服务器进程 通信的实例,write_fifo的作用类似于客户端,可以打开多个客户端向一个服务器发送请求信息,read_fifo类似于服务器,它适时监控着FIFO的读端,当有数据时,读出并进行处理,但是有一个关键的问题是,每一个客户端必须预先知道服务器提供的FIFO接口,下图显示了这种安排: 三、消息队列 消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。 1、特点 消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。 消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。 2、原型1 #include 2 // 创建或打开消息队列:成功返回队列ID,失败返回-13 int msgget(key_t key, int flag);4 // 添加消息:成功返回0,失败返回-15 int msgsnd(int msqid, const void *ptr, size_t size, int flag);6 // 读取消息:成功返回消息数据的长度,失败返回-17 int msgrcv(int msqid, void *ptr, size_t size, long type,int flag);8 // 控制消息队列:成功返回0,失败返回-19 int msgctl(int msqid, int cmd, struct msqid_ds *buf); 在以下两种情况下,msgget将创建一个新的消息队列: 如果没有与键值key相对应的消息队列,并且flag中包含了IPC_CREAT标志位。 key参数为IPC_PRIVATE。 函数msgrcv在读取消息队列时,type参数有下面几种情况: type == 0,返回队列中的第一个消息; type >0, returns the first message in the queue with the message type type
Type
< 0,返回队列中消息类型值小于或等于 type 绝对值的消息,如果有多个,则取类型值最小的消息。 可以看出,type值非 0 时用于以非先进先出次序读消息。也可以把 type 看做优先级的权值。(其他的参数解释,请自行Google之) 3、例子 下面写了一个简单的使用消息队列进行IPC的例子,服务端程序一直在等待特定类型的消息,当收到该类型的消息以后,发送另一种特定类型的消息作为反馈,客户端读取该反馈并打印出来。 msg_server.c 1 #include 2 #include 3 #include 4 5 // 用于创建一个唯一的key 6 #define MSG_FILE "/etc/passwd" 7 8 // 消息结构 9 struct msg_form {10 long mtype;11 char mtext[256];12 };13 14 int main()15 {16 int msqid;17 key_t key;18 struct msg_form msg;19 20 // 获取key值21 if((key = ftok(MSG_FILE,'z')) < 0)22 {23 perror("ftok error");24 exit(1);25 }26 27 // 打印key值28 printf("Message Queue - Server key is: %d.\n", key);29 30 // 创建消息队列31 if ((msqid = msgget(key, IPC_CREAT|0777)) == -1)32 {33 perror("msgget error");34 exit(1);35 }36 37 // 打印消息队列ID及进程ID38 printf("My msqid is: %d.\n", msqid);39 printf("My pid is: %d.\n", getpid());40 41 // 循环读取消息42 for(;;) 43 {44 msgrcv(msqid, &msg, 256, 888, 0);// 返回类型为888的第一个消息45 printf("Server: receive msg.mtext is: %s.\n", msg.mtext);46 printf("Server: receive msg.mtype is: %d.\n", msg.mtype);47 48 msg.mtype = 999; // 客户端接收的消息类型49 sprintf(msg.mtext, "hello, I'm server %d", getpid());50 msgsnd(msqid, &msg, sizeof(msg.mtext), 0);51 }52 return 0;53 } msg_client.c 1 #include 2 #include 3 #include 4 5 // 用于创建一个唯一的key 6 #define MSG_FILE "/etc/passwd" 7 8 // 消息结构 9 struct msg_form {10 long mtype;11 char mtext[256];12 };13 14 int main()15 {16 int msqid;17 key_t key;18 struct msg_form msg;19 20 // 获取key值21 if ((key = ftok(MSG_FILE, 'z')) < 0) 22 {23 perror("ftok error");24 exit(1);25 }26 27 // 打印key值28 printf("Message Queue - Client key is: %d.\n", key);29 30 // 打开消息队列31 if ((msqid = msgget(key, IPC_CREAT|0777)) == -1) 32 {33 perror("msgget error");34 exit(1);35 }36 37 // 打印消息队列ID及进程ID38 printf("My msqid is: %d.\n", msqid);39 printf("My pid is: %d.\n", getpid());40 41 // 添加消息,类型为88842 msg.mtype = 888;43 sprintf(msg.mtext, "hello, I'm client %d", getpid());44 msgsnd(msqid, &msg, sizeof(msg.mtext), 0);45 46 // 读取类型为777的消息47 msgrcv(msqid, &msg, 256, 999, 0);48 printf("Client: receive msg.mtext is: %s.\n", msg.mtext);49 printf("Client: receive msg.mtype is: %d.\n", msg.mtype);50 return 0;51 }四、信号量 信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。 1、特点 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。 信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作。 每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数。 支持信号量组。 2、原型 最简单的信号量是只能取 0 和 1 的变量,这也是信号量最常见的一种形式,叫做二值信号量(Binary Semaphore)。而可以取多个正整数的信号量被称为通用信号量。 Linux 下的信号量函数都是在通用的信号量数组上进行操作,而不是在一个单一的二值信号量上进行操作。 1 #include 2 // 创建或获取一个信号量组:若成功返回信号量集ID,失败返回-13 int semget(key_t key, int num_sems, int sem_flags);4 // 对信号量组进行操作,改变信号量的值:成功返回0,失败返回-15 int semop(int semid, struct sembuf semoparray[], size_t numops); 6 // 控制信号量的相关信息7 int semctl(int semid, int sem_num, int cmd, ...); 当semget创建新的信号量集合时,必须指定集合中信号量的个数(即num_sems),通常为1; 如果是引用一个现有的集合,则将num_sems指定为 0 。 在semop函数中,sembuf结构的定义如下: 1 struct sembuf 2 {3 short sem_num; // 信号量组中对应的序号,0~sem_nums-14 short sem_op; // 信号量值在一次操作中的改变量5 short sem_flg; // IPC_NOWAIT, SEM_UNDO6 } 其中 sem_op 是一次操作中的信号量的改变量: 若sem_op >0, which means that the process releases the corresponding number of resources and adds the value of sem_op to the value of the semaphore. If processes are sleeping waiting for this semaphore, wrap them.
If sem_op < 0, request the resource of the absolute value of sem_op.
If sem_flg specifies IPC_NOWAIT, the semop function returns EAGAIN with an error.
If sem_flg does not specify an IPC_NOWAIT, increase the semncnt value of the semaphore by 1, and then suspend the process until the following occurs:
If the corresponding number of resources can satisfy the request, subtract the value of the semaphore from the absolute value of sem_op, and the function returns successfully.
When the corresponding number of resources does not meet the request, this operation is related to sem_flg.
When the corresponding number of resources can satisfy the request, the semncnt value of the semaphore minus 1, and the value of the semaphore minus the absolute value of sem_op. Successful return
This semaphore was deleted, and the function smeop returned EIDRM in error.
The process captures the signal and returns from the signal processing function. In this case, the semncnt value of this semaphore is subtracted by 1, and the function semop error returns EINTR.
If sem_op = = 0, the process blocks until the corresponding value of the semaphore is 0:
If sem_flg specifies IPC_NOWAIT, an error returns EAGAIN.
If sem_flg does not specify an IPC_NOWAIT, increase the semncnt value of the semaphore by 1, and then suspend the process until the following occurs:
When the semaphore is 0, the function returns immediately.
If the value of the semaphore is not 0, the function action is determined according to sem_flg:
If the value of the semaphore is 0, the semzcnt of the semaphore is subtracted by 1, and the function semop is returned successfully.
This semaphore was deleted, and the function smeop returned EIDRM in error.
The process captures the signal and returns from the signal processing function. In this case, the semncnt value of this semaphore is reduced by 1, and the function semop error returns EINTR.
There are many commands in the semctl function. Here are two commonly used ones:
SETVAL: used to initialize the semaphore to a known value. The required value is passed as a val member of the federated semun. You need to set the semaphore before it is used for the first time.
IPC_RMID: deletes a semaphore collection. If you do not delete the semaphore, it will continue to exist in the system, even if the program has exited, it may cause problems the next time you run the program, and the semaphore is a limited resource.
3. Example 1 # include 2 # include 3 # include 4 5 / / for semctl initialization 6 union semun 7 {8 int val; / * for SETVAL*/ 9 struct semid_ds * buf; 10 unsigned short * array; 11}; 12 13 / / initialize semaphore 14 int init_sem (int sem_id, int value) 15 {16 union semun tmp; 17 tmp.val = value 18 if (semctl (sem_id, 0, SETVAL, tmp) =-1) 19 {20 perror ("Init Semaphore Error"); 21 return-1; 22} 23 return 0; 24} 25 26 / / P Operation: 27 / / if the signal value is 1, get the resource and set the signal value-1 28 / / if the signal value is 0, the process suspends and waits for 29 int sem_p (int sem_id) 30 {31 struct sembuf sbuf 32 sbuf.sem_num = 0; / * serial number * / 33 sbuf.sem_op =-1; / * P Operation * / 34 sbuf.sem_flg = SEM_UNDO; 35 36 if (semop (sem_id, & sbuf, 1) =-1) 37 {38 perror ("P operation Error"); 39 return-1; 40} 41 return 0 42} 43 44 / / V operation: 45 / / release resources and set the signal value + 1 46 / / if processes are waiting, wake them up 47 int sem_v (int sem_id) 48 {49 struct sembuf sbuf; 50 sbuf.sem_num = 0; / * sequence number * / 51 sbuf.sem_op = 1; / * V operation * / 52 sbuf.sem_flg = SEM_UNDO 53 54 if (semop (sem_id, & sbuf, 1) =-1) 55 {56 perror ("V operation Error"); 57 return-1; 58} 59 return 0; 60} 61 62 / / Delete semaphore set 63 int del_sem (int sem_id) 64 {65 union semun tmp 66 if (semctl (sem_id, 0, IPC_RMID, tmp) =-1) 67 {68 perror ("Delete Semaphore Error"); 69 return-1; 70} 71 return 0; 72} 73 74 75 int main () 76 {77 int sem_id; / / semaphore set ID 78 key_t key; 79 pid_t pid 8081 / / get the key value 82 if ((key = ftok (".",'z') < 0) 83 {84 perror ("ftok error"); 85 exit (1); 86} 87 88 / / create a semaphore set with only one semaphore 89 if ((sem_id = semget (key, 1, IPC_CREAT | 0666)) =-1) 90 {91 perror ("semget error") 92 exit (1); 93} 94 95 / / initialization: initial value set to 0 resource occupied 96 init_sem (sem_id, 0); 97 98 if ((pid = fork ()) =-1) 99 perror ("Fork Error"); 100 else if (pid = = 0) / * child process * / 101 {102 sleep (2) 103 printf ("Process child: pid=%d\ n", getpid ()); 104 sem_v (sem_id); / * release resources * / 105} 106 else / * parent process * / 107 {108 sem_p (sem_id); / * waiting resources * / 109 printf ("Process father: pid=%d\ n", getpid ()); 110 sem_v (sem_id) / * release resources * / 1111del_sem (sem_id); / * Delete semaphore set * / 112} 113return 0t114}
If the above example does not add a semaphore, the parent process will finish execution first. A semaphore is added here for the parent process to wait until the child process has finished execution.
5. Shared memory
Shared memory (Shared Memory) means that two or more processes share a given storage area.
1. Characteristics
Shared memory is the fastest IPC because the process accesses memory directly.
Because multiple processes can operate at the same time, synchronization is required.
Semaphores + shared memory are usually used together, and semaphores are used to synchronize access to shared memory.
2. Prototype 1 # include 2 / / create or get a shared memory: return shared memory ID successfully, failed to return-13 int shmget (key_t key, size_t size, int flag); 4 / / connect shared memory to the address space of the current process: successfully return a pointer to shared memory, failed to return-15 void * shmat (int shm_id, const void * addr, int flag) 6 / / disconnect from shared memory: 0 for success and-17 int shmdt (void * addr) for failure; 8 / Information about controlling shared memory: 0 for success and-19 int shmctl for failure (int shm_id, int cmd, struct shmid_ds * buf)
When you create a segment of shared memory with the shmget function, you must specify its size;, and if you reference an existing shared memory, specify size as 0.
When a piece of shared memory is created, it cannot be accessed by any process. You must use the shmat function to connect the shared memory to the address space of the current process, and after a successful connection, the shared memory area object is mapped to the address space of the calling process, which can then be accessed as if it were local space.
The shmdt function is used to disconnect connections established by shmat. Note that this is not removing the shared memory from the system, but that the current process can no longer access the shared memory.
The shmctl function can perform a variety of operations on shared memory, depending on the parameter cmd. Commonly used is IPC_RMID, which removes the shared memory from the system.
3. Examples
In the following example, the combination of shared memory, semaphore and message queue is used to communicate between the server process and the client process.
Shared memory is used to transfer data
Semaphores are used to synchronize
Message queuing is used to notify the server to read after the client modifies the shared memory.
Server.c
1 # include 2 # include 3 # include / / shared memory 4 # include / / semaphore 5 # include / / message queue 6 # include / / memcpy 7 8 / / message queue structure 9 struct msg_form {10 long mtype; 11 char mtext; 12}; 13 14 / / consortium for semctl initialization 15 union semun 16 {17 int val; / * for SETVAL*/ 18 struct semid_ds * buf; 19 unsigned short * array; 20} 21 22 / initialize semaphores 23 int init_sem (int sem_id, int value) 24 {25 union semun tmp; 26 tmp.val = value; 27 if (semctl (sem_id, 0, SETVAL, tmp) = =-1) 28 {29 perror ("Init Semaphore Error"); 30 return-1; 31} 32 return 0 33} 34 35 / / P Operation: 36 / / if the signal value is 1, get the resource and set the signal value-1 37 / / if the signal value is 0, the process suspends and waits for 38 int sem_p (int sem_id) 39 {40 struct sembuf sbuf; 41 sbuf.sem_num = 0; / * sequence number * / 42 sbuf.sem_op =-1; / * P Operation * / 43 sbuf.sem_flg = SEM_UNDO 44 45 if (semop (sem_id, & sbuf, 1) =-1) 46 {47 perror ("P operation Error"); 48 return-1; 49} 50 return 0; 51} 52 53 / V Operation: 54 / / release resources and signal value + 1 55 / / if processes are pending, wake them up 56 int sem_v (int sem_id) 57 {58 struct sembuf sbuf 59 sbuf.sem_num = 0; / * serial number * / 60 sbuf.sem_op = 1; / * V operation * / 61 sbuf.sem_flg = SEM_UNDO; 62 63 if (semop (sem_id, & sbuf, 1) =-1) 64 {65 perror ("V operation Error"); 66 return-1; 67} 68 return 0 69} 70 71 / / Delete semaphore set 72 int del_sem (int sem_id) 73 {74 union semun tmp; 75 if (semctl (sem_id, 0, IPC_RMID, tmp) =-1) 76 {77 perror ("Delete Semaphore Error"); 78 return-1; 79} 80 return 0; 81} 82 83 / / create a semaphore set 84 int creat_sem (key_t key) 85 {86 int sem_id 87 if ((sem_id = semget (key, 1, IPC_CREAT | 0666)) =-1) 88 {89 perror ("semget error"); 90 exit (- 1); 91} 92 init_sem (sem_id, 1); / * initial value is set to 1 resource unoccupied * / 93 return sem_id; 94} 95 96 97 int main () 98 {99 key_t key;100 int shmid, semid, msqid;101 char * shm 102 char data [] = "this is server"; 103 struct shmid_ds buf1; / * for deleting shared memory * / 104 struct msqid_ds buf2; / * for deleting message queues * / 105 struct msg_form msg / * message queuing is used to notify the other party that shared memory has been updated * / 106 107 / / get the key value 108 if ((key = ftok (".",'z') < 0) 109 {110 perror ("ftok error"); 111 exit (1) 112} 113114 / / create shared memory 115 if ((shmid = shmget (key, 1024, IPC_CREAT | 0666)) =-1) 116 {117 perror ("Create Shared Memory Error"); 118 exit (1); 119} 120121 / / connect shared memory 122shm = (char*) shmat (shmid, 0,0) 123 if ((int) shm = =-1) 124 {125 perror ("Attach Shared Memory Error"); 126 exit (1); 127} 128 129 130 / / create message queue 131 if ((msqid = msgget (key, IPC_CREAT | 0777)) =-1) 132 {133 perror ("msgget error"); 134 exit (1) 136137 / create semaphores 138semid = creat_sem (key); 139140 / read data 141while (1) 142 {143msgrcv (msqid, & msg, 1,888,0); / * read messages of type 888 * / 144if (msg.mtext = ='q') / * quit-jump out of loop * / 145break 146 if (msg.mtext ='r') / * read-read shared memory * / 147 {148 sem_p (semid); 149 printf ("% s\ n", shm); 150 sem_v (semid); 151} 152} 153 / / disconnect 155 shmdt (shm) 156157 / * Delete shared memory, message queues, semaphores * / 158shmctl (shmid, IPC_RMID, & buf1); 159msgctl (msqid, IPC_RMID, & buf2); 160del_sem (semid); 161return 0t162}
Client.c
1 # include 2 # include 3 # include / / shared memory 4 # include / / semaphore 5 # include / / message queue 6 # include / / memcpy 7 8 / / message queue structure 9 struct msg_form {10 long mtype; 11 char mtext; 12}; 13 14 / / consortium for semctl initialization 15 union semun 16 {17 int val; / * for SETVAL*/ 18 struct semid_ds * buf; 19 unsigned short * array; 20} 21 22 / / P operation: 23 / / if the signal value is 1, get the resource and set the signal value-1 24 / / if the signal value is 0, the process suspends and waits for 25 int sem_p (int sem_id) 26 {27 struct sembuf sbuf; 28 sbuf.sem_num = 0; / * sequence number * / 29 sbuf.sem_op =-1; / * P operation * / 30 sbuf.sem_flg = SEM_UNDO 31 32 if (semop (sem_id, & sbuf, 1) =-1) 33 {34 perror ("P operation Error"); 35 return-1; 36} 37 return 0; 38} 39 40 / V Operation: 41 / / release resources and signal value + 1 42 / / if processes are pending, wake them 43 int sem_v (int sem_id) 44 {45 struct sembuf sbuf 46 sbuf.sem_num = 0; / * serial number * / 47 sbuf.sem_op = 1; / * V operation * / 48 sbuf.sem_flg = SEM_UNDO; 49 50 if (semop (sem_id, & sbuf, 1) =-1) 51 {52 perror ("V operation Error"); 53 return-1; 54} 55 return 0; 56} 57 58 59 int main () 60 {61 key_t key 62 int shmid, semid, msqid; 63 char * shm; 64 struct msg_form msg; 65 int flag = 1; / * while loop condition * / 66 67 / / get the key value 68 if ((key = ftok (".",'z') < 0) 69 {70 perror ("ftok error"); 71 exit (1) 72} 73 74 / / get 75 if of shared memory ((shmid = shmget (key, 1024, 0)) =-1) 76 {77 perror ("shmget error"); 78 exit (1); 79} 8081 / / connect shared memory 82 shm = (char*) shmat (shmid, 0,0); 83 if ((int) shm = =-1) 84 {85 perror ("Attach Shared Memory Error") 86 exit (1); 87} 88 89 / / create message queue 90 if ((msqid = msgget (key, 0)) =-1) 91 {92 perror ("msgget error"); 93 exit (1); 94} 95 96 / / get semaphore 97 if ((semid = semget (key, 0,0)) =-1) 98 {99 perror ("semget error") 100 exit (1); 101} 102 103 / / write data 104 printf ("* *\ n"); 105 printf ("* IPC *\ n"); 106 printf ("* Input r to send data to server. *\ n "); 107 printf (" * Input q to quit. *\ n "); 108 printf (" * *\ n "); 109110 while (flag) 111 {112 char / printf (" Please input command: "); 114 scanf ("% c ", & c) 115 switch (c) 116 {117 case'rang sem_p 118 printf ("Data to send:"); 119 sem_p (semid); / * access Resources * / 120 scanf ("% s", shm); 121 sem_v (semid) / * release resources * / 122 / * clear the standard input buffer * / 123 while ((c=getchar ())! ='\ n'& & clocked buffer EOF); 124 msg.mtype = 888; 125 msg.mtext ='r' / * send a message to notify the server to read the data * / 126 msgsnd (msqid, & msg, sizeof (msg.mtext), 0); 127 break;128 case'qtransactions msqid, & msg, sizeof (msg.mtext), 0) 132 flag = 0bot 133 break;134 default:135 printf ("Wrong input!\ n"); 136 / * clear the standard input buffer * / 137 while ((c=getchar ())! ='\ n'& & cased input EOF) 140141 / / disconnect 142 shmdt (shm); 143144return 0posi145}
Note: when scanf () enters a character or string,\ n is left in the buffer, so you need to empty the standard input buffer after each input operation. But since the gcc compiler does not support fflush (stdin) (which is just an extension of standard C), we use an alternative:
1 while ((c=getchar ())!) ='\ n'& & caterpillar EOF); Summary of five communication methods
1. Pipes: slow speed, limited capacity, and only parent-child processes can communicate
2.FIFO: any process can communicate, but the speed is slow
3. Message queue: the capacity is limited by the system, and you should pay attention to the problem that you didn't finish reading the data last time when you read it for the first time.
4. Semaphores: complex messages cannot be passed, they can only be used for synchronization
5. Shared memory area: the capacity can be easily controlled and the speed is fast, but keep synchronized. For example, when one process is writing, another process should pay attention to the problem of reading and writing, which is equivalent to thread safety in threads. Of course, the shared memory area can also be used for inter-thread communication, but this is not necessary. Threads already share a piece of memory in the same process.
Thank you for reading! This is the end of this article on "what are the five modes of communication between processes?". I hope the above content can be of some help to you, so that you can learn more knowledge. If you think the article is good, you can share it for more people to see!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.