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

来源:互联网 发布:sql server2005企业版 编辑:程序博客网 时间:2024/05/29 14:36
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 = 4process 1:count = 1                 process 2:count = 6process 1:count = 2                 process 2:count = 8process 1:count = 3                 process 2:count = 10process 1:count = 5                 process 2:count = 12process 1:count = 7                 process 2:count = 14process 1:count = 9                 process 2:count = 16process 1:count = 11                process 2:count = 18process 1:count = 13                process 2:count = 20process 1:count = 15process 1:count = 17process 1:count = 19
阅读全文
0 0
原创粉丝点击