A small example of comprehensive application of semaphore set and shared memory

Requirements: Use semaphore sets and shared memory to achieve: a process stores the data "Nice to meet you" in the shared memory in a cyclic inversion, and a process cyclically outputs the content of the shared memory. Make sure to invert and print once.

Analysis: These two processes can be written as two source files, one file corresponds to one process, as can be seen from the title requirements, these two processes implement a synchronization relationship between processes , that is, if you want the process to print information, you must use another A process completes the inversion of the contents of the array, and then the process cannot be inverted immediately after the inversion of the process is completed once. The printing process must complete the printing of the last inversion. Use the PV operation to show the relationship between them as follows:
insert image description here

//reverse.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
#include <sys/shm.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>

union semun {
    
    
    int val;
};
void sem_init(int semid, int num, int val) //信号灯集初始化函数
{
    
    
    union semun sem;
    sem.val = val;
    semctl(semid, num, SETVAL, sem);
}
void sem_op(int semid, int num, int op) //pv操作函数
{
    
    
    struct sembuf buf;
    buf.sem_num = num;
    buf.sem_op = op;
    buf.sem_flg = 0;
    semop(semid, &buf, 1);
}
char reverse(char *head, char *tail)
{
    
    
    while (head < tail)
    {
    
    
        *head ^= *tail;
        *tail ^= *head;
        *head++ ^= *tail--;
    }
}
int main(int argc, char const *argv[])
{
    
    
    char s[32] = {
    
    0};
    //创建key值
    key_t key = ftok(".", 'a');
    if (key < 0)
    {
    
    
        perror("ftok err");
        return -1;
    }
    //shmget
    int shmid = shmget(key, 32, IPC_CREAT | IPC_EXCL | 0666);
    if (shmid <= 0)
    {
    
    
        if (errno = EEXIST)
            shmid = shmget(key, 32, 0666);
        else
        {
    
    
            perror("shmget err");
            return -1;
        }
    }
    //shmat
    char *p = (char *)shmat(shmid, NULL, 0);
    if (p == (char *)-1)
    {
    
    
        perror("shmat err");
        return -1;
    }
    //semget
    int semid = semget(key, 2, IPC_CREAT | IPC_EXCL | 0666);
    if (semid <= 0)
    {
    
    
        if (errno = EEXIST)
            semid = semget(key, 1, 0666);
        else
        {
    
    
            perror("semget err");
            return -1;
        }
    }
    else
    {
    
    
        sem_init(semid, 0, 1); //初始化信号灯集0
        sem_init(semid, 1, 0); //初始化信号灯集1
    }
    fputs("请输入字符串:", stdout);
    fgets(p, 32, stdin);
    if (p[strlen(p) - 1] == '\n')
        p[strlen(p) - 1] = '\0';
    char *head = NULL;
    char *tail = NULL;
    while (1)
    {
    
    
        head = p;
        tail = p + strlen(p) - 1;
        sem_op(semid, 0, -1);
        reverse(p, p + strlen(p) - 1); //倒置
        printf("倒置...%p\n",p);
        sem_op(semid, 1, 1);
    }
    shmdt(p);
    shmctl(shmid, IPC_RMID, NULL);
    //删除信号灯集
    semctl(semid, 0, IPC_RMID);
    return 0;
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
#include <sys/shm.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>


union semun {
    
    
    int val;
};
void sem_init(int semid, int num, int val) //信号灯集初始化函数
{
    
    
    union semun sem;
    sem.val = val;
    semctl(semid, num, SETVAL, sem);
}
void sem_op(int semid, int num, int op) //pv操作函数
{
    
    
    struct sembuf buf;
    buf.sem_num = num;
    buf.sem_op = op;
    buf.sem_flg = 0;
    semop(semid, &buf, 1);
}

int main(int argc, char const *argv[])
{
    
    
    // char s[32] = {0};
    //创建key值
    key_t key = ftok(".", 'a');
    if (key < 0)
    {
    
    
        perror("ftok err");
        return -1;
    }
    //shmget
    int shmid = shmget(key, 32, IPC_CREAT | IPC_EXCL | 0666);
    if (shmid <= 0)
    {
    
    
        if (errno = EEXIST)
            shmid = shmget(key, 32, 0666);
        else
        {
    
    
            perror("shmget err");
            return -1;
        }
    }
    //shmat
    char *p = (char *)shmat(shmid, NULL, 0);
    if (p == (char *)-1)
    {
    
    
        perror("shmat err");
        return -1;
    }
    //semget
    int semid = semget(key, 2, IPC_CREAT | IPC_EXCL | 0666);
    if (semid <= 0)
    {
    
    
        if (errno = EEXIST)
            semid = semget(key, 1, 0666);
        else
        {
    
    
            perror("semget err");
            return -1;
        }
    }
    else
    {
    
    
        sem_init(semid, 0, 1); //初始化信号灯集0
        sem_init(semid, 1, 0); //初始化信号灯集1
    }
    while (1)
    {
    
    
        sem_op(semid, 1, -1);
        printf("%s\n",p); //dayin
        sleep(1);
        sem_op(semid, 0, 1);
    }

    shmdt(p);
    shmctl(shmid, IPC_RMID, NULL);
    //删除信号灯集
    semctl(semid, 0, IPC_RMID);
    return 0;
}
  • In the above program, the initialization of the semaphore and the PV operation are encapsulated with functions, which makes the code more modular and less messy, and at the same time, it is more convenient to realize the functions.
  • The two data exchanges use the ^= method, which does not need to set the third variable, and the data exchange is completely realized in the original address space

Guess you like

Origin blog.csdn.net/weixin_43624626/article/details/132383924