Linux 信号量的使用

信号量的作用是给共享内存加锁

信号量只允许进程进行等待和发送信号操作

通用信号量应用场景较少,一般使用二元信号量

信号量和互斥锁的原理是类似的

引用头文件

#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>

相关函数

1.初始化信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);
  • sem:需要初始化的信号量。
  • pshared:传入0值表示线程间共享,传入非零值表示进程间共享。
  • value:信号量的初始值(计数器的初始值)。

返回值说明:

  • 初始化信号量成功返回0,失败返回-1。
2.销毁信号量
int sem_destroy(sem_t *sem);

参数说明:

  • sem:需要销毁的信号量。

返回值说明:

  • 销毁信号量成功返回0,失败返回-1。
3.等待信号量(申请信号量)
int sem_wait(sem_t *sem);

参数说明:

  • sem:需要等待的信号量。

返回值说明:

  • 等待信号量成功返回0,信号量的值减一。
  • 等待信号量失败返回-1,信号量的值保持不变。
4.发布信号量(释放信号量)
int sem_post(sem_t *sem);

参数说明

  • sem:需要发布的信号量。

返回值说明:

  • 发布信号量成功返回0,信号量的值加一。
  • 发布信号量失败返回-1,信号量的值保持不变。

示例代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>
#include <semaphore.h>

int main()
{
    int shmky = ftok("./test1.cpp",'a');                                 //通过同一个文件生成相同的key,用于读取同一个内存
    if(shmky<0){
        perror("ftok");
        return -2;
    }


    int shmid = shmget(shmky,128,0755|IPC_CREAT);                      //1.创建共享内存空间
    if(shmid<0){
        perror("shmget");
        exit(1);
    }
    printf("shmget success %d\n",shmid);                                //创建的共享内存可用 ipcrm -m id删除
    system("ipcs -m");                                                  //调用内核,显示当前系统的共享内存

    sem_t sem;
    int sem_id = sem_init(&sem, 1, 1);

    int pid = fork();//创建4个进程同时操作同一个共享内存
    if(pid ==0)
    {
        int pid2 = fork();
        if(pid2 ==0)
        {
            int* i = (int*)shmat(shmid,NULL,0);                                 //将char类型数据关联到共享内存     
            sem_wait(&sem); 
            (*i)=0; 
            sem_post(&sem);                             
            for(int x = 0;x<100;x++)
            {
                sem_wait(&sem); 
                printf("process1    i=%d\n",*i);
                (*i)++;
                sem_post(&sem);  
            }
            shmdt(i);   
        } else{
            int* i = (int*)shmat(shmid,NULL,0);                                 //将char类型数据关联到共享内存                                    
            for(int x = 0;x<100;x++)
            {
                sem_wait(&sem); 
                printf("process2    i=%d\n",*i);
                (*i)++;
                sem_post(&sem);  
            }
            shmdt(i);   
        }
    }else{
        int pid3 = fork();
        if(pid3 ==0)
        {
            int* i = (int*)shmat(shmid,NULL,0);                                 //将char类型数据关联到共享内存                                    
            for(int x = 0;x<100;x++)
            {
                sem_wait(&sem); 
                printf("process3    i=%d\n",*i);
                (*i)++;
                sem_post(&sem);  
            }
            shmdt(i);   
        } else{
            int* i = (int*)shmat(shmid,NULL,0);                                 //将char类型数据关联到共享内存                                    
            for(int x = 0;x<100;x++)
            {
                sem_wait(&sem); 
                printf("process4    i=%d\n",*i);
                (*i)++;
                sem_post(&sem);  
            }
            shmdt(i);   
            sleep(5);
            sem_destroy(&sem);
            shmctl(shmid,IPC_RMID,NULL);
        }
    }   
}

要验证代码的话,将某个进程中的sem_post注释,即可发现程序会卡在该进程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值