进程之间的共享资源的互斥访问

一.文件锁

//获取锁,如果已经被占用立即返回,errno被设置为EAGAIN
int try_lock_fd(int fd)
{
    struct flock fl; 
    fl.l_start = 0;
    fl.l_len = 0;
    fl.l_pid = 0;
    fl.l_type = F_WRLCK;
    fl.l_whence = SEEK_SET;
    //如果锁已经被占用,errno会被设置为 EAGAIN
    return fcntl(fd, F_SETLK, &fl);  
}
//获取锁,如果已经被占用则等待
int lock_fd(int fd) 
{
    struct flock fl; 
    fl.l_start = 0;
    fl.l_len = 0;
    fl.l_pid = 0;
    fl.l_type = F_WRLCK;
    fl.l_whence = SEEK_SET;

    return fcntl(fd, F_SETLKW, &fl);
}
//释放文件锁即返回,errno被设置为EAGAIN
int unlock_fd(int fd)
{
    struct flock fl;
    fl.l_start = 0;
    fl.l_len = 0;
    fl.l_pid = 0;
    fl.l_type = F_UNLCK;
    fl.l_whence = SEEK_SET;

    return fcntl(fd, F_SETLK, &fl);
}

二.共享内存+内存信号量(又称无名信号量)
下面是一个简单的测试程序:

#include<semaphore.h>
#include<stdio.h>
#include<errno.h>
#include</usr/include/sys/mman.h>

sem_t* psem = NULL;

int main()
{
    pid_t pid;
    psem =  mmap(NULL, sizeof(sem_t),
               PROT_READ|PROT_WRITE,
               MAP_ANON|MAP_SHARED, -1, 0);
    if(MAP_FAILED == psem)
    {
        printf("mmap failed !\n");
        return -1;
    }

    if(-1== sem_init(psem, 1, 0))
     {
        printf("sem_init err:%d\n", errno);

     }
     pid = fork();
     if(pid < 0)
     {
        printf("fork err:%d", errno);
     }

     if(0 == pid)
     {
         sleep(5);
        if( -1 == sem_post(psem))
        {
            printf("post sem ! errno:%d\n", errno);
        }
        else
        }
        else
        {
            printf("post sem secceed !\n");
        }
     }

     if(pid > 0)
     {
        if(-1 == sem_wait(psem))
        {

            printf("wait sem errno:%d\n", errno);
        }
        else
        {
            printf("wait sem succeed !\n");
        }
     }

     printf("process exit\n");
     return 0;
}

三.共享内存+锁
共享内存+互斥锁或者读写锁或者原子锁,都可以实现进程间互斥
以原子锁为例;

#include <stdio.h>
#include<unistd.h>
#include</usr/include/sys/mman.h>
inline int atom_cmp_set(unsigned long *mem,unsigned long newval,unsigned long oldval)
{
        unsigned char  res;

        __asm __volatile ("lock;" 
                    "cmpxchg %3, %1;"
                    "sete %0;"
                    : "=a" (res)
                    : "m" (*mem), "a" (oldval), "r" (newval)
                    : "cc", "memory" );

          return (int) res;
}
int main()
{

    int ret = 0;
    pid_t pid = 0;
    unsigned long* atom_val = mmap(NULL, sizeof(unsigned long),
                           PROT_READ|PROT_WRITE,
                                          MAP_ANON|MAP_SHARED, -1, 0); 
    if(MAP_FAILED == atom_val) 
    {   
        printf("err in mmap !");
        return -1; 
    }   
    *atom_val = 0;

    if((pid = fork()) < 0)
    {   
        printf("fork err !\n");
        return 0;
    }   
   ret = atom_cmp_set(atom_val, 1, 0);
    if(1 == ret)
    {
        printf("in %s process atom_cmp_set secceed atom_val:%d\n", pid == 0  ? "child":"parent", *atom_val);
    }
    else
    {
        printf("in %s process atom_cmp_set failed atom_val:%d \n", pid == 0  ? "child":"parent", *atom_val);
    }
    return 0;
}

输出:

in parent process atom_cmp_set secceed atom_val:1
in child process atom_cmp_set failed atom_val:1 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值