LINUX中IPC信号灯

信号灯:多进程编程中需要关注进程间同步及互斥。同步是指多个进程为了完成同一个任务相互 协作运行,而互斥是指不同的进程为了争夺有限的系统资源(硬件或软件资源)而相互竞争 运行。
信号量是用来解决进程间的同步与互斥问题的一种进程间通信机制,它是一个特殊的变 量,变量的值代表着关联资源的可用数量。若等于 0 则意味着目前没有可用的资源。
信号量:
根据信号量的值可以将信号量分为二值信号量和计数信号量:
1、二值值信号量:信号量的值只有 0 和 1 值,若资源被锁住,信号量值为 0,若资源可 用则信号量值为 1;
2、计数信号量:信号量的值在 0 到一个大于 1 的值(最大 32767)。该计数表示可用 的资源的个数。 信号量只能进行的两个原子操作:P 操作:V 操作
1、 P 操作:如果有可用的资源(信号量值>0),则占用一个资源(给信号量值减 1); 如果没有可用的资源(信号量值=0),则进程被阻塞直到系统将资源分配给该进程 (进入信号量的等待队列,等到资源后唤醒该进程)。

	2、V 操作:如果在该信号量的等待队列中有进程在等待资源,则唤醒一个阻塞进程; 如果没有进程等待它,则释放一个资源(给信号量值加 1) 
定义信号变量;  sem_t sem1 sem2
初始化信号量
P操作
V操作

在这里插入图片描述
信号灯:
信号灯集合(可以包含多个信号灯) IPC对象是一个信号灯集(多个信号量)
在这里插入图片描述
所有的函数是对一个集合的操作:
创建信号灯
int semget(key_t key, int nsems, int semflg);在这里插入图片描述
`#include<sys/types.h>
#include<sys/sem.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>

int main()
{
    int semid;


    semid =semget(IPC_PRIVATE,3, 0777);
    if(semid <0)
    {
            printf("creat semaphore failure\n");
            return -1;
    }
    printf("creat semaphore sucess semid = %d\n",semid);
    system("ipcs -s");
    while(1);

//      msgctl(msgid,IPC_RMID,NULL);
//      system("ipcs -q");
    //system("ipcrm -m shmid");
    return 0;
}`

在这里插入图片描述
删除信号灯
int semctl ( int semid, int semnum, int cmd,…union semun arg(不是地址));
在这里插入图片描述

#include<sys/types.h>
#include<sys/sem.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>

int main()
{
        int semid;


        semid =semget(IPC_PRIVATE,3, 0777);
        if(semid <0)
        {
                printf("creat semaphore failure\n");
                return -1;
        }
        printf("creat semaphore sucess semid = %d\n",semid);
        system("ipcs -s");

        //删除信号灯
        semctl(semid,0,IPC_RMID);
        system("ipcs -s");
        return 0;
}

在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>

sem_t sem;//初始化信号量
void *fun(void *var)
{
        int j;
        sem_wait(&sem);//运行到这里处于阻塞状态
        for(j = 0;j < 10; j++)
        {
                usleep(10);
                printf("this is fun j = %d\n",j);
        }
}
int main()
{
        int i;
        char str[] = "hello linux\n";
        pthread_t tid;
        int ret;


        sem_init(&sem,0,0);//信号量的初始化为0
        ret = pthread_create(&tid,NULL,fun,(void *)str);
        if(ret < 0)
        {
                printf("creat thread failure\n");
                return -1;
        }
        for(i = 0; i < 10;i++)
        {
                usleep(100);
                printf("this is main fun i = %d\n",i);
        }
        sem_post(&sem);//唤醒线程
        while(1);
        return 0;
}

在这里插入图片描述
这里要主要pthread的库在运行的时候 gcc smoop.c -ipthread
要加上连接的库的名称

(4)int semop ( int semid, struct sembuf *opsptr, size_t nops);
在这里插入图片描述
SETVAL:设置信号灯的值 信号灯的初始化,类似sem_init;
union semun
{
int val;
//SETVAL:设置信号灯的值
struct semid_ds *buf;
// IPC_STAT (获取对象属性)
//IPC_SET (设置对象属性)
unsigned short array; / Array for GETALL, SETALL */
struct seminfo __buf; / Buffer for IPC_INFO (Linux-specific) */
};

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
#include<sys/ipc.h>
#include<sys/sem.h>
//sem_t sem;//初始化信号量
int semid;
union semun
{
        int val;
        struct semid_ds *buf;
        unsigned short *array;
        struct seminfo *_buf;
};
union semun mysemun;
struct sembuf mysembuf;
void *fun(void *var)
{
        int j;

        //sem_wait(&sem);//运行到这里处于阻塞状态
        mysembuf.sem_op = -1;
        semop(semid,&mysembuf,1);
        for(j = 0;j < 10; j++)
        {
                usleep(10);
                printf("this is fun j = %d\n",j);
        }
}
int main()
{
        int i;
        char str[] = "hello linux\n";
        pthread_t tid;
        int ret;
        semid = semget(IPC_PRIVATE ,3,0777);
        if(semid < 0)
        {
                printf("creat semaphore failure\n");
                return -1;
        }
        printf("creat semaphore sucess,semid = %d\n",semid);
        system("ipcs -s");
        mysemun.val = 0;
        semctl(semid, 0, SETVAL,mysemun);//信号量的初始化
        mysembuf.sem_num = 0;
        mysembuf.sem_flg = 0;
        //sem_init(&sem,0,0);//信号量的初始化为0

        ret = pthread_create(&tid,NULL,fun,(void *)str);
        if(ret < 0)
        {
                printf("creat thread failure\n");
                return -1;
        }
        for(i = 0; i < 10;i++)
        {
                usleep(100);
                printf("this is main fun i = %d\n",i);
        }
        mysembuf.sem_op =1;
        semop(semid,&mysembuf,1);
        //sem_post(&sem);//唤醒线程
        while(1);
        return 0;
}

在这里插入图片描述
semctl不仅可以删除,还可以初始化信号量

通过信号量实现两个无亲缘关系的通信

在这里插入图片描述
服务器端

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
#include<sys/ipc.h>
#include<sys/sem.h>
//sem_t sem;//初始化信号量
int semid;
union semun
{
        int val;
        struct semid_ds *buf;
        unsigned short *array;
        struct seminfo *_buf;
};
union semun mysemun;
struct sembuf mysembuf;
int main()
{
        int i;
        pthread_t tid;
        int key;

        key = ftok("./a.c",'a');
        if(key < 0)
        {
                printf("creat key failure\n");
                return -1;
        }
        printf("creat key sucess\n");
        semid = semget(key ,3,IPC_CREAT |  0777);

        if(semid < 0)
        {
                printf("creat semaphore failure\n");
                return -2;
        }
        printf("creat semaphore sucess,semid = %d\n",semid);
        system("ipcs -s");
        //mysemun.val = 0;
        //semctl(semid, 0, SETVAL,mysemun);//信号量的初始化
        mysembuf.sem_num = 0;
        mysembuf.sem_flg = 0;
        //sem_init(&sem,0,0);//信号量的初始化为0

        for(i = 0; i < 10;i++)
        {
                usleep(100);
                printf("this is main fun i = %d\n",i);
        }
        mysembuf.sem_op =1;
        semop(semid,&mysembuf,1);
        //sem_post(&sem);//唤醒线程
        while(1);
        return 0;
}

客户端

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
#include<sys/ipc.h>
#include<sys/sem.h>
//sem_t sem;//初始化信号量
int semid;
union semun
{
        int val;
        struct semid_ds *buf;
        unsigned short *array;
        struct seminfo *_buf;
};
union semun mysemun;
struct sembuf mysembuf;
int main()
{
        int i;
        pthread_t tid;
        int key;

        key = ftok("./a.c",'a');
        if(key < 0)
        {
                printf("creat key failure\n");
                return -1;
        }
        printf("creat key sucess\n");
        semid = semget(key ,3,IPC_CREAT |  0777);

        if(semid < 0)
        {
                printf("creat semaphore failure\n");
                return -2;
        }
        printf("creat semaphore sucess,semid = %d\n",semid);
        system("ipcs -s");
        mysemun.val = 0;
        semctl(semid, 0, SETVAL,mysemun);//信号量的初始化
        mysembuf.sem_num = 0;
        mysembuf.sem_flg = 0;
        //sem_init(&sem,0,0);//信号量的初始化为0
        mysembuf.sem_op = -1;
        semop(semid,&mysembuf,1);
        for(i = 0; i < 10;i++)
        {
                usleep(100);
                printf("this is main fun i = %d\n",i);
        }
        //mysembuf.sem_op =1;  P操作
        //semop(semid,&mysembuf,1);
        //sem_post(&sem);//唤醒线程
        while(1);
        return 0;
}

在这里插入图片描述
先运行客户端client代码,在运行服务端server代码,发现运行server代码后,客户端代码同步运行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值