Talk C chestnuts together (106th back: C language instance-producer and consumer question 2)
Hello, the last time we talked aboutProducer and consumer problems. When you leave the rest of your time, your words will go right. Let's talk C chestnuts together!
In the last session, we introduced the producer and consumer issues, and provided the solution and pseudocode for the problem. In today's chapter, we will convert pseudo code into C code, that isImplement producer and consumer problems through specific code.
Detailed implementation stepsAs follows:
1. Define the semaphore joint type and shared memory struct type by yourself; 2. Use the main parameters in the program:-p and-c to indicate the producer and consumer processes respectively;
The above steps are as follows:Steps for producer and consumer to use togetherThe following describes the implementation steps of the producer and consumer respectively.
Producer implementation steps:
1. create a semaphore in the producer and initialize the semaphore; 2. create shared memory in the producer and link the shared memory address to the producer process space. 3. perform P operations on semaphores. 4. determine whether the number of products in the pool is smaller than the size of the pool. If the number is smaller than, go to the next step. Otherwise, wait for the consumer to take the product away. the producer produces a product and puts the product in the pool. Then, the number of products is increased by 1. 6. perform the V Operation on the semaphore. 7. repeat steps 3 to 6 until the products cannot be stored in the pool; 8. delete semaphores; 9. disconnect the address link of the shared memory from the producer address space and delete the shared memory;
Consumer implementation steps:
1. obtain the semaphores created in the producer in consumption. 2. obtain the shared memory created in the producer from the consumer and link the address of the shared memory to the consumer's process space. 3. perform P operations on semaphores. 4. determine whether the number of products in the pool is greater than zero. If the number is greater than zero, go to the next step. Otherwise, wait for the producer to produce the product. the consumer removes a product from the pool, and then reduces the number of products by one. 6. perform the V Operation on the semaphore. 7. repeat steps 3 to 6 until there is no product in the pool; 8. disconnect the address link of the shared memory from the consumer address space;
The readers will not write the code in the text, and the detailed code will be put into my resources. You can download and use it.
In the code, we encapsulate the P/V Operation of the semaphore to make the code simpler.
We delayed the actions taken by the producer to produce products and consumers, mainly to facilitate viewing the program running results and better demonstrate the problems between the producer and consumer; the latency of consumers and producers can be controlled by themselves, and the latency of consumers in code is half of the latency of producers.
In addition, the size of the pool can also be customized. In the code, the size of the pool is 8, which can accommodate 8 int-type variables.
We use shared memory in the code to communicate between producer processes and consumer processes. You can use other inter-process communication methods. For example, pipelines, FIFO queues, and message queues.
I was asked whether a global variable and global array can be used to replace the shared memory. My answer is no, because the global variable is only global in a process, and we use two processes, which obviously does not work. More directly, if the producer process updates the global variables and global arrays, then the consumer process will not see the content updated by the producer. in the consumer's opinion, they have not changed, or the number of products is zero and the pool is empty.
The following is the running result of the program. For more information, see:
$. /A-p & // run the compiled program in the background. Use the parameter-p to start the producer process [1] 3562 // The producer process has been started. The PID is 3562 $ [pid: 3562] producer is running producer count: 0 // before the producer produces the product, the number of products is empty, and there is no produce data in the pool. count: 1, data: 1 producer count: 1 produce data. count: 2, data: 2 producer count: 2 produce data. count: 3, data: 3 // The producer produces three products and stores them in the pool. /a-c // run the compiled program on the foreground and use parameter-c to start the consumer process [pid: 3563] customer is running // The producer process has been started, PID is 3563 customer count: 3 // before the consumer removes the product, the number of products is 3, and three products in the pool get data. count: 3, data: 3 // The consumer takes one product producer count: 2 produce data. count: 3, data: 3 // The producer produces one product customer count: 3 get data. count: 3, data: 3 customer count: 2 get data. count: 2, data: 2 // The consumer takes two more products, producer count: 1 produce data. count: 2, data: 2 // The producer produces another product, customer count: 2 get data. count: 2, data: 2 customer count: 1 get data. count: 1, data: 1 // The consumer takes two products producer count: 0 produce data. count: 1, data: 1 // the producer has produced another product, customer count: 1 get data. count: 1, data: 1 customer count: 0 the buf is empty // the Consumer removes one product, and no product is available in the pool. [pid: 3563] customer running finished // end of the consumer process $ producer count: 0 produce data. count: 1, data: 1 producer count: 1 produce data. count: 2, data: 2 producer count: 2 produce data. count: 3, data: 3 producer count: 3 produce data. count: 4, data: 4 producer count: 4 produce data. count: 5, data: 5 producer count: 5 produce data. count: 6, data: 6 producer count: 6 produce data. count: 7, data: 7 producer count: 7 produce data. count: 8, data: 8 producer count: 8 the buf is full // the producer continuously produces 8 Products, and the pool has already merged [pid: 3562] producer running finished // producer end // enter the return key and return it to the terminal [1] + Done
From the running results of the program, we can see that the producer process and the consumption process run alternately. One process adds a product to the pool, and the other process removes the product from the pool. However, in any case, the number of products in the pool is consistent with that of the producer and consumer, benefiting from semaphores synchronizing the producer process and consumer process. In addition, we have processed the code. When the pool is full, the producer stops producing the product and ends the producer process, instead of waiting for the consumer to remove the product from the pool. When there is no product in the pool, the consumer no longer removes the product from the pool and ends the consumer process, rather than waiting for the producer to produce the product. Otherwise, our program will never end.
Let's talk about the example of producers and consumers. I want to know what examples will be provided later, and I will try again.