进程通信程序管理---共享内存和信号量(Linux)

ShareMemory1.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <sys/ipc.h>  
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/sem.h>

#define SHMKEY 1234  //为共享内存命名
#define SHMSIZE  4096  //定义共享内存容量
#define SEMKEY  1234 //不相关的进程可以通过它访问一个信号量,它代表程序可能要使用的某个资源

union semun
{
    int  val;    /* Value for SETVAL */
    struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
    unsigned short  *array;  /* Array for GETALL, SETALL */
    struct seminfo  *__buf;  /* Buffer for IPC_INFO(Linux specific) */
};

int sem_p(int id)
{
    struct sembuf buf;
    int ret;

    buf.sem_num = 0;  //对第一个信号量进行semop操作,除非使用一组信号量,否则它为0
    buf.sem_op = -1;   //进行减一操作(对该信号量执行等待操作)
    buf.sem_flg = SEM_UNDO;  //防止进程异常退出没有释放信号量

    ret = semop(id,&buf,1);  //只有一个信号量,只需操作一次,它的作用是改变信号量的值
    if(-1 == ret)
    {
        perror("semop");
        return 1;
    }
    return 0;
}


int sem_v(int id)
{
    struct sembuf buf;
    int ret;

    buf.sem_num = 0;  
    buf.sem_op = 1;  
    buf.sem_flg = SEM_UNDO; 

    ret = semop(id,&buf,1);  
    if(-1 == ret)
    {
        perror("semop");
        return 1;
    }
    return 0;
}
int main()
{
    int shmid,semid,ret;
    void *shmaddr;
    int count = 0,tmp;
    union semun union_sem;

    shmid = shmget(SHMKEY,SHMSIZE,IPC_CREAT|IPC_EXCL); // 创建共享内容,并返回一个共享内存标识,第一个参数为共享内存的名称;第二个参数为共享内存容量;第三个参数为权限标志,如果共享内存不存在则创建,如果已经存在则产生错误;
    if(-1 == shmid)
    {
        perror("shmget");
        exit(1);
    }

    shmaddr = shmat(shmid,NULL,0);//启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间,返回一个指向共享内存第一个字节的指针。第二个参数指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址;第三个为标志位,通常为0;
    if((void *)-1 == shmaddr)
    {
        perror("shmaddr");
        exit(1);
    }

    semid = semget(SEMKEY,1,IPC_CREAT|IPC_EXCL); //创建信号量,只需要1个,返回信号量标识符
    if(-1 == semid)
    {
        perror("semget");
        exit(1);
    }

    union_sem.val = 1; //联合体,用于初始化信号量
    ret = semctl(semid,0,SETVAL,union_sem); //初始化信号量,初始化为1。SETVAL:用来把信号量初始化为一个已知的值。这个值通过union semun中的val成员设置,其作用是在信号量第一次使用前对它进行设置
    if(-1 == ret)
    {
        perror("semctl");
        exit(1);
    }

    *(int *)shmaddr = count;  //将count放进物理内存

    while(1)
    {
        sem_p(semid);   //P操作,对信号量减一
        tmp = *(int *)shmaddr;
        if(tmp>20)
        {
            sem_v(semid); //注意要释放信号量
            break;
        }
        printf("process 1:count = %d\n",tmp);
        sleep(1);
        tmp++;
        *(int *)shmaddr = tmp;
        sem_v(semid);  //V操作,对信号量加一
    }
    ret = shmdt(shmaddr);   //解除映射(共享内存)
    if(-1 == ret)
    {
        perror("shmdt");
        exit(1);
    }

    sleep(1);
    shmctl(shmid,IPC_RMID,NULL);  //删除共享内存
    semctl(semid,0,IPC_RMID);   //删除信号量

    return 0;
}
ShareMemory2.c



#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <sys/ipc.h>  
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/sem.h>

#define SHMKEY 1234  //为共享内存命名
#define SHMSIZE  4096  //定义共享内存容量
#define SEMKEY  1234 //不相关的进程可以通过它访问一个信号量,它代表程序可能要使用的某个资源

union semun
{
    int  val;    /* Value for SETVAL */
    struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
    unsigned short  *array;  /* Array for GETALL, SETALL */
    struct seminfo  *__buf;  /* Buffer for IPC_INFO(Linux specific) */
};

int sem_p(int id)
{
    struct sembuf buf;
    int ret;

    buf.sem_num = 0;  //对第一个信号量进行semop操作,除非使用一组信号量,否则它为0
    buf.sem_op = -1;   //进行减一操作(对该信号量执行等待操作)
    buf.sem_flg = SEM_UNDO;  //防止进程异常退出没有释放信号量

    ret = semop(id,&buf,1);  //只有一个信号量,只需操作一次,它的作用是改变信号量的值
    if(-1 == ret)
    {
        perror("semop");
        return 1;
    }
    return 0;
}


int sem_v(int id)
{
    struct sembuf buf;
    int ret;

    buf.sem_num = 0;  
    buf.sem_op = 1;  
    buf.sem_flg = SEM_UNDO; 

    ret = semop(id,&buf,1);  
    if(-1 == ret)
    {
        perror("semop");
        return 1;
    }
    return 0;
}
int main()
{
    int shmid,semid,ret;
    void *shmaddr;
    int tmp;
    union semun union_sem;

    shmid = shmget(SHMKEY,SHMSIZE,0); // 创建共享内容,并返回一个共享内存标识,第一个参数为共享内存的名称;第二个参数为共享内存容量;第三个参数为权限标志,如果共享内存不存在则创建,如果已经存在则产生错误;
    if(-1 == shmid)
    {
        perror("shmget");
        exit(1);
    }

    shmaddr = shmat(shmid,NULL,0);//启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间,返回一个指向共享内存第一个字节的指针。第二个参数指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址;第三个为标志位,通常为0;
    if((void *)-1 == shmaddr)
    {
        perror("shmaddr");
        exit(1);
    }

    semid = semget(SEMKEY,1,0); //创建信号量,只需要1个,返回信号量标识符
    if(-1 == semid)
    {
        perror("semget");
        exit(1);
    }


    while(1)
    {
        sem_p(semid);   //P操作,对信号量减一
        tmp = *(int *)shmaddr;
        if(tmp>20)
        {
            sem_v(semid); 
            break;
        }
        printf("process 2:count = %d\n",tmp);
        sleep(1);
        tmp++;
        *(int *)shmaddr = tmp;
        sem_v(semid);  //V操作,对信号量加一
    }
    ret = shmdt(shmaddr);   //解除映射(共享内存)
    if(-1 == ret)
    {
        perror("shmdt");
        exit(1);
    }

    return 0;
}



执行结果:

process 1:count = 0                 process 2:count = 4
process 1:count = 1                 process 2:count = 6
process 1:count = 2                 process 2:count = 8
process 1:count = 3                 process 2:count = 10
process 1:count = 5                 process 2:count = 12
process 1:count = 7                 process 2:count = 14
process 1:count = 9                 process 2:count = 16
process 1:count = 11                process 2:count = 18
process 1:count = 13                process 2:count = 20
process 1:count = 15
process 1:count = 17
process 1:count = 19









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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值