⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 p_c.c

📁 多线程的“生产者消费者”问题的解决方案。采用消息队列缓冲技术。
💻 C
字号:
#include <stdio.h>#include <time.h>#include <unistd.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/sem.h>#define NEED_P 2#define NEED_C 3#define WORKS_P 6#define WORKS_C 4#define BUF_LENGTH (sizeof(struct mybuffer))#define LETTER_NUM 3#define SHM_MODE 0600#define SEM_ALL_KEY 1234#define SEM_EMPTY 0#define SEM_FULL 1//缓冲区结构(循环队列)struct mybuffer{    char letter[LETTER_NUM];    int head;    int tail;    int is_empty;};//得到5以内的一个随机数int get_random(){    int t;    srand((unsigned)(getpid() + time(NULL)));    t = rand() % 5;    return t;}//得到A~Z的一个随机字母char get_letter(){    char a;    srand((unsigned)(getpid() + time(NULL)));    a = (char)((char)(rand() % 26) + 'A');    return a;}//P操作void p(int sem_id, int sem_num){    struct sembuf xx;    xx.sem_num = sem_num;    xx.sem_op = -1;    xx.sem_flg = 0;    semop(sem_id, &xx, 1);}//V操作void v(int sem_id, int sem_num){    struct sembuf xx;    xx.sem_num = sem_num;    xx.sem_op = 1;    xx.sem_flg = 0;    semop(sem_id, &xx, 1);}//主函数int main(int argc, char * argv[]){    int i, j;    int shm_id, sem_id;    int num_p = 0, num_c = 0;    struct mybuffer * shmptr;    char lt;    time_t now;    pid_t pid_p, pid_c;        sem_id = semget(SEM_ALL_KEY, 2, IPC_CREAT | 0660);    if (sem_id >= 0)    {        printf("Main process starts. Semaphore created.\n");    }    semctl(sem_id, SEM_EMPTY, SETVAL, LETTER_NUM);    semctl(sem_id, SEM_FULL, SETVAL, 0);        if ((shm_id = shmget(IPC_PRIVATE, BUF_LENGTH, SHM_MODE)) < 0)    {        printf("Error on shmget.\n");        exit(1);    }    if ((shmptr = shmat(shm_id, 0, 0)) == (void *)-1)    {        printf("Error on shmat.\n");        exit(1);    }    shmptr->head = 0;    shmptr->tail = 0;    shmptr->is_empty = 1;        while ((num_p++) < NEED_P)    {        if ((pid_p = fork()) < 0)        {            printf("Error on fork.\n");            exit(1);        }        //如果是子进程,开始创建生产者        if (pid_p == 0)        {            if ((shmptr = shmat(shm_id, 0, 0)) == (void *)-1)            {                printf("Error on shmat.\n");                exit(1);            }            for (i = 0; i < WORKS_P; i++)            {                p(sem_id, SEM_EMPTY);                sleep(get_random());                shmptr->letter[shmptr->tail] = lt = get_letter();                shmptr->tail = (shmptr->tail + 1) % LETTER_NUM;                shmptr->is_empty = 0;                now = time(NULL);                printf("%02d:%02d:%02d\t", localtime(&now)->tm_hour, localtime(&now)->tm_min, localtime(&now)->tm_sec);                for (j = (shmptr->tail - 1 >= shmptr->head) ? (shmptr->tail - 1) : (shmptr->tail - 1 + LETTER_NUM); !(shmptr->is_empty) && j >= shmptr->head; j--)                {                    printf("%c", shmptr->letter[j % LETTER_NUM]);                }                printf("\tProducer %d puts '%c'.\n", num_p, lt);                fflush(stdout);                v(sem_id, SEM_FULL);            }            shmdt(shmptr);            exit(0);        }    }    while (num_c++ < NEED_C)    {        if ((pid_c = fork()) < 0)        {            printf("Error on fork.\n");            exit(1);        }        //如果是子进程,开始创建消费者        if (pid_c == 0)        {            if ((shmptr = shmat(shm_id, 0, 0)) == (void *)-1)            {                printf("Error on shmat.\n");                exit(1);            }            for (i = 0; i < WORKS_C; i++)            {                p(sem_id, SEM_FULL);                sleep(get_random());                lt = shmptr->letter[shmptr->head];                shmptr->head = (shmptr->head + 1) % LETTER_NUM;                shmptr->is_empty = (shmptr->head == shmptr->tail);                now = time(NULL);                printf("%02d:%02d:%02d\t", localtime(&now)->tm_hour, localtime(&now)->tm_min, localtime(&now)->tm_sec);                for (j = (shmptr->tail - 1 >= shmptr->head) ? (shmptr->tail - 1) : (shmptr->tail - 1 + LETTER_NUM); !(shmptr->is_empty) && j >= shmptr->head; j--)                {                    printf("%c", shmptr->letter[j % LETTER_NUM]);                }                printf("\tConsumer %d gets '%c'.\n", num_c, lt);                fflush(stdout);                v(sem_id, SEM_EMPTY);            }            shmdt(shmptr);            exit(0);        }    }        //主控程序最后退出    while(wait(0) != -1);    shmdt(shmptr);    shmctl(shm_id, IPC_RMID, 0);    semctl(sem_id, IPC_RMID, 0);    printf("Main process ends.\n");    fflush(stdout);    exit(0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -