posix信号量对system V共享内存的同步控制

9 篇文章 0 订阅

Linux进程间通信的方式有多种,包括无名管道、FIFO、消息队列、共享内存、信号量。
其中共享内存是在内存中开辟一个空间,使得不同进程都可以共享访问,进程间的数据传递可以不经过内核,是进程间通信最快的一种,但是共享内存没有同步机制,一般情况下,使用信号量、互斥锁等同步机制来对共享内存进行同步控制。

信号量是一种用于提供不同进程间或给定一个进程不同线程间同步手段的原语。一个进程可以在某个信号量上执行的三种操作为:
1、创建(create)一个信号量,这还要求调用者给定初始值;
2、等待(wait)一个信号量,该操作测试一个信号量的值,如果其值小于或等于0,那就阻塞,一但值变为大于0,就将它减1 。
3、挂出(post) 一个信号量,该操作将信号量值加1。

写两个独立的程序,写进程读入标准输入,通过共享内存将输入内容传递给读进程,读进程将共享内存中的数据写入标准输出。

共有头文件global_def.h的定义

#ifndef __GLOBAL_DEF_H__
#define __GLOBAL_DEF_H__

#define SHMPATH "/home/hello/dev-learn/shm/sharemem.shm"
#define SEMPATH "/sem.1234"

#define BUF_SIZE  200

#include <semaphore.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#endif

写进程shmwrite.c

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>
#include <errno.h>

#include "global_def.h"

int main(int argv, char ** argc)
{
    key_t shm_key;
    int shm_id;
    char *buf;
    void *shm;

    sem_t *sem;

    shm_key = ftok(SHMPATH, 0x58);
    printf("%s: shm_key = %d\n", argc[0], shm_key);

    shm_id = shmget(shm_key, BUF_SIZE, 0666|IPC_CREAT);
    printf("shm_id = %d\n", shm_id);
    if (shm_id == -1)
    {
        fprintf(stderr, "shmget failed because of %s\n", strerror(errno));
        return -1;
    }

    if ((shm = shmat(shm_id, 0, 0)) == (void *)-1)
    {
        fprintf(stderr, "shmat failed becausef of %s\n", strerror(errno));
        return -1;
    }

    if ((sem = sem_open(SEMPATH, 0)) == SEM_FAILED)
    {
        fprintf(stderr, "sem_open failed because of %s\n", strerror(errno));
        return -1;
    }

    buf = (char *)shm;
    while(1)
    {
        scanf("%s", buf);
        printf("input is: %s\n", buf);
        if(sem_post(sem) == 0)
        {
            fprintf(stderr, "sem_postfailed because of %s\n", strerror(errno));
        }
        if (strcmp(buf, "quit") == 0)
        {
            if (shmdt(shm) == -1)
            {
                fprintf(stderr, "shmdt failed!!\n");
                return -1;
            }
            if (sem_close(sem) == -1)
            {
                fprintf(stderr, "sem_close faield because of %s\n", strerror(errno));
                return -1;
            }
            printf("bye-bye!\n");
            return 0;
        }
    }

    return 0;
}

读进程shmread.c

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>
#include <errno.h>

#include "global_def.h"


int main(int argv, char ** argc)
{
    key_t shm_key;
    int shm_id;
    char *buf;
    void * shm;

    sem_t *sem;

    shm_key = ftok(SHMPATH, 0x58);
    printf("shm_key = %d\n", shm_key);

    shm_id = shmget(shm_key, BUF_SIZE, 0666|IPC_CREAT);
    printf("shm_id = %d\n", shm_id);
    if (shm_id == -1)
    {
        fprintf(stderr, "shmget failed because of %s\n", strerror(errno));
        return -1;
    }

    if ((shm = shmat(shm_id, 0, 0)) == (void *)-1)
    {
        fprintf(stderr, "shmat failed because of %s\n", strerror(errno));
        return -1;
    }
    buf = (char *)shm;

    sem = sem_open(SEMPATH, O_CREAT, S_IROTH, 0);
    if (sem == SEM_FAILED)
    {
        fprintf(stderr, "sem_open failed because of %s\n", strerror(errno));
        return -1;
    }

    while(1)
    {
        if (sem_wait(sem) == -1)
        {
            fprintf(stderr, "sem_wait failed because of %s\n", strerror(errno));
        }
        if (strcmp(buf, "quit") == 0)
        {
            if (shmdt(shm) == -1)
            {
                fprintf(stderr, "shmdt failed because of %s\n", strerror(errno));
                return -1;
            }
            if (shmctl(shm_id, IPC_RMID, 0) == -1)
            {
                fprintf(stderr, "shmctl failed because of %s\n", strerror(errno));
                return -1;
            }
            if (sem_close(sem) == -1)
            {
                fprintf(stderr, "sem_close failed because of %s\n", strerror(errno));
                return -1;
            }
            if (sem_unlink(SEMPATH) == -1)
            {
                fprintf(stderr, "sem_unlink failed because of %s\n", strerror(errno));
                return -1;
            }
            printf("bye-bye!\n");
            return 0;
        }
        printf("read from shm: %s\n", buf);
    }

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值