shm sem msg

IPC(interprocess communication)概念.进程通讯如shm,sem,smg.

IPC键值获得:

key_t ftok( const char * fname, int id )

fname:文件地址; id: 0-255自定义; 返回IPC键值。不同进程可用同样的方式获得相同的键值,以便semget,shmget,smgget使用。

int semget(key_t key, int nsems, int semflg);

key: ftok获得的键值;nsems信号量的个数;semflg:IPC_CREAT | 0666(创建,可读写);返回,信号量的描述符,信号量个数为nsems。


union semun_u
{
    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
};
int semctl(int semid,int semnum,int cmd, /*union semun arg*/);
semid:semget获得的fd;semnum:操作第几个信号量(0为第一个);cmd:命令如SETVAL(设置该信号量semval值,用于阻塞。需要:semun_u.val(=1)),GETVAL,IPC_RMID(删除);返回-1错误。注意:semctl两个进程不要都用这个函数来初始化SETVAL(设置一个即可),否则出错。

int semop(int semid, struct sembuf *sops, unsigned nsops);

semid;sops如下结构;nsops:操作sops的个数。

struct sembuf
{
unsigned short sem_num; /* semaphore number */第几个信号量0开始
short sem_op; /* semaphore operation */-1P操作,+1V操作。
short sem_flg; /* operation flags */SEM_UNDO(崩溃还原以前的semval)等标志
};


而int semget(key_t key, int nsems, int semflg);需要的key可以用ftok得到。

共享内存操作:

创建共享内存:

ftok,

shmget,

shmat(映射内存地址),

创建信号量:

ftok,

semget(一般配置1个信号量)

semctl(配置某一个编号信号量的值(临界资源数),PV操作(百度百科))

如果是互斥信号量的话,应该设置信号量Sem=1,但是当有5个进程都访问的话,最后在该信号量的链表里会有4个在等待,也是说S=-4,那么第一个进程执行了V操作使S加1,释放了资源,下一个应该能够执行,但唤醒的这个进程在执行P操作时因S〈0,也还是执行不了,这是怎么回事呢?当一个进程阻塞了的时候,它已经执行过了P操作,并卡在临界区那个地方。当唤醒它时就立即进入它自己的临界区,并不需要执行P操作了,当执行完了临界区的程序后,就执行V操作

注意系统调用semctl中的最后一个参数是一个联合类型的副本,而不是一个指向联合类型的指针


需要注意的是,对于semun联合体最好自己定义,否则GCC编译器可能会报“semun大小未知”。

while(1)

{

    semop(nSemID, &((sembuf)({0, -1, SEM_UNDO})), 1)//semop(信号量-1,),SEM_UNDO表示本进程挂掉,信号量恢复之前的值,防止资源锁死。

    操作shmat返回地址

    semop(nSemID, &((sembuf)({0, +1, SEM_UNDO})), 1)信号量+1

}

shmdt;

shmctl(lShareMemID, IPC_RMID, NULL);//注:如果在此之前程序崩溃,共享内存将不会被释放。

if(-1 != SemID)
{
    semctl(SemID, 0, IPC_RMID, unSemArg);//释放
}



union

{

    int a;

    char b[10];

}

a="ab",b[0]=b,b[1]=a

大小>最大成员,并且是最大类型的整数倍。这个=12


key_t ftok( const char * fname, int id );

fname文件地址,id:1-255但是我测试有些数据不可以。返回-1错误,否则返回其他int型,包括负数。

int shmget(key_t key, size_t size, int shmflg);

开辟内存;key由ftok生成;size:空间大小;shmflg=IPC_CREAT | 0666:表示不存在创建IPC描述符,存在得到相应IPC描述符;返回-1错误。

void *shmat(int shmid, const void *shmaddr, int shmflg);

映射空间;shmid:IPC描述符;shmaddr:NULL系统分配地址;shmflg:除了0x10000(SHM_RDONLY)为读写,直接=0。

此后操作返回的地址就可以了。

使用int shmctl(shmid,IPC_RMID, NULL)删除共享内存;和int shmdt(const void *shmaddr);断开与共享内存的映射。参考

    if(NULL != shmAddr)
    {
        shmdt(shmAddr);
        if(shmIPCid > 0)
        {
            shmctl(shmIPCid, IPC_RMID, NULL);
        }
    }

int semget(key_t key, int nsems, int semflg);

创建信号量。nsems信号量数组个数,shmflg=IPC_CREAT | 0666没有旧创建,有直接返回描述符。返回-1错误,(注:也判断0也不能用,测试一些ftok中id配置不对,这里返回0,导致信号量不能锁住。


int semctl(int semid,int semnum,int cmd, /*union semun arg*/);

semid描述符;semnum:操作信号数组的第几个,0开始;cmd=SETVAL是设置:semun->val的。这里的val我目前的猜测应该时信号量可通过的数量,如val=2,使用semop阻塞的时候可以同时通过两个。一般设置为1。

semctl(semIPCid, SEM_SHARE_MEM_NUM, IPC_RMID, tempsemun/*val=0*/);删除信号量。


int semop(int semid, struct sembuf *sops, unsigned nsops);//一直阻塞

int semtimedop(int semid, struct sembuf *sops, unsigned nsops, struct timespec *timeout);//超时返回-1

semid描述符;sops->sem_op=-1进入使用,+1出去使用,sops->sem_flg=SEM_UNDO;nsops操作多少个信号量,从sops->sem_flg开始计数,1个=1;timeout配置超时时间;

struct sembuf

{

unsigned short sem_num; /* semaphore number */操作信号数组的第几个,0开始

short sem_op; /* semaphore operation */-1表示阻塞多一,+1表示阻塞减一。

short sem_flg; /* operation flags */ = SEM_UNDO表示本进程挂掉,信号量恢复之前的值,防止资源锁死。

};

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

#include <iostream>
#include "shm_sem_info.h"


using namespace std;


static int readSemFileOk()
{
    FILE *fd;
    int tempi = 0;
    fd = fopen(SEMAPHORE_SETVALUE_PATH, "r");
    if(NULL == fd)
    {
        printf("surpas:%s,%d,fd not exist;\n", __FILE__, __LINE__);
        if(fd = fopen(SEMAPHORE_SETVALUE_PATH, "w"))
        {
            fclose(fd);
            return 1;
        }
        printf("ERROR -- surpas:%s,%d,fd not exist;\n", __FILE__, __LINE__);
        return -1;
    }
    //fscanf(fd,"file%dfile",&tempi);
    //printf("surpas:%s,%d, tempi = %d;\n", __FILE__, __LINE__, tempi);
    //if(1 == tempi)
    //{
        //fprintf(fd,"1");
    //    return 0;
    //}
    //else
    //{
    //    fprintf(fd,"file1file");
    //    return 1;
    //}
    fclose(fd);
    return 0;
}

static void resetSemFileValue()
{
    remove(SEMAPHORE_SETVALUE_PATH);
}

shmSemFile::shmSemFile()
{
    shmKeyID = -1;
    semKeyID = -1;
    shmIPCid = -1;
    semIPCid = -1;
    shmAddr = NULL;
}
shmSemFile::~shmSemFile()
{
    deleteShareMem();
    deleteSemaphore();
    resetSemFileValue();
}
void* shmSemFile::createShareMemery()
{
    shmKeyID = ftok(IPC_FILE_PATH, IPC_FTOK_ID);
    if(-1 == shmKeyID)
    {
        return NULL;
    }
    cout<<"surpas:"<<__FILE__<<","<<__LINE__<<",ftok="<<shmKeyID<<endl;
    
    shmIPCid = shmget(shmKeyID, SHARE_MEM_SIZE, IPC_CREAT | 0666);
    if(-1 == shmIPCid)
    {
        return NULL;
    }
    printf("surpas:%s,%d,shmIPCid=%d;\n", __FILE__, __LINE__, shmIPCid);
    
    shmAddr = shmat(shmIPCid, NULL, 0);
    if((void *)-1 == shmAddr)
    {
        return NULL;
    }
    
    printf("surpas:%s,%d,shmAddr=%p;\n", __FILE__, __LINE__, shmAddr);
    return shmAddr;
    
}

int shmSemFile::createSemaphore()
{
    semKeyID = ftok(IPC_SEM_FILE_PATH, IPC_FTOK_ID);//IPC_SEM_FILE_PATH
    if(-1 == semKeyID)
    {
        printf("surpas:%s,%d,shmKeyID=%d\n", __FILE__, __LINE__, semKeyID);
        return -1;
    }
    cout<<"surpas:"<<__FILE__<<","<<__LINE__<<",ftok="<<semKeyID<<endl;
    
    semIPCid = semget(semKeyID, SEMAPHORE_TOTAL_NUM, IPC_CREAT | 0666);
    if(-1 == semIPCid)
    {
        return -2;
    }
    printf("surpas:%s,%d,semIPCid=%d;\n", __FILE__, __LINE__, semIPCid);

    
    if(1 == readSemFileOk())//两个进程不能都设置SETVAL
    {

        union semun_u tempsemun;
        int tempflag;
        tempsemun.val = 1;
        tempflag = semctl(semIPCid, SEM_SHARE_MEM_NUM, SETVAL, tempsemun);
        //tempflag = semctl(semIPCid, SEM_SHARE_MEM_NUM, GETVAL);
        printf("surpas:%s,%d,%d\n", __FILE__, __LINE__,tempflag);
        if(-1 == tempflag)
        {
            return -3;
        }
    }
    
    return 1;
}

int shmSemFile::semLock()
{
    int tempflag;
    struct sembuf tempsembuf = {0, -1, SEM_UNDO};
    struct timespec tempOutTime = {1, 0};
    tempflag = semop(semIPCid, &tempsembuf, 1);//sussed return 0
    //tempflag = semtimedop(SEM_SHARE_MEM_NUM, &tempsembuf, 1, &tempOutTime);//sussed return 0
    if(-1 == tempflag)
    {
        return -1;
    }
    tempflag = semctl(semIPCid, SEM_SHARE_MEM_NUM, GETVAL);
    return 0;
}

int shmSemFile::semUnlock()
{
    int tempflag;
    struct sembuf tempsembuf = {0, +1, SEM_UNDO};
    struct timespec tempOutTime = {1, 0};
    tempflag = semop(semIPCid, &tempsembuf, 1);//sussed return 0
    //tempflag = semtimedop(SEM_SHARE_MEM_NUM, &tempsembuf, 1, &tempOutTime);//sussed return 0
    printf("surpas:%s,%d,semtimedop=%d;\n", __FILE__, __LINE__, tempflag);    
    if(-1 == tempflag)
    {
        return -1;
    }
    return 0;
}


int shmSemFile::readShareMem()
{

}

int shmSemFile::getShareMem()
{

}

void shmSemFile::deleteShareMem()
{
    if(NULL != shmAddr)
    {
        shmdt(shmAddr);
        printf("surpas:%s,%d,shmAddr=%p;\n", __FILE__, __LINE__, shmAddr);
        if(shmIPCid > 0)
        {
            shmctl(shmIPCid, IPC_RMID, NULL);
        }
    }
    
}

void shmSemFile::deleteSemaphore()
{
    union semun_u tempsemun;
    tempsemun.val = 0;
    if(semIPCid > 0)
    {
        semctl(semIPCid, SEM_SHARE_MEM_NUM, IPC_RMID, tempsemun);
    }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#DESCRIPTION:Resource namespaces pidns01 pidns01 pidns02 pidns02 pidns03 pidns03 pidns04 pidns04 pidns05 pidns05 pidns06 pidns06 pidns10 pidns10 pidns12 pidns12 pidns13 pidns13 pidns16 pidns16 pidns17 pidns17 pidns20 pidns20 pidns30 pidns30 pidns31 pidns31 pidns32 pidns32 mqns_01 mqns_01 mqns_01_clone mqns_01 -m clone mqns_01_unshare mqns_01 -m unshare mqns_02 mqns_02 mqns_02_clone mqns_02 -m clone mqns_02_unshare mqns_02 -m unshare mqns_03 mqns_03 mqns_03_clone mqns_03 -clone mqns_04 mqns_04 mqns_04_clone mqns_04 -clone netns_netlink netns_netlink netns_breakns_ip_ipv4_netlink netns_breakns.sh netns_breakns_ip_ipv6_netlink netns_breakns.sh -6 netns_breakns_ip_ipv4_ioctl netns_breakns.sh -I netns_breakns_ip_ipv6_ioctl netns_breakns.sh -6I netns_breakns_ns_exec_ipv4_netlink netns_breakns.sh -e netns_breakns_ns_exec_ipv6_netlink netns_breakns.sh -6e netns_breakns_ns_exec_ipv4_ioctl netns_breakns.sh -eI netns_breakns_ns_exec_ipv6_ioctl netns_breakns.sh -6eI netns_comm_ip_ipv4_netlink netns_comm.sh netns_comm_ip_ipv6_netlink netns_comm.sh -6 netns_comm_ip_ipv4_ioctl netns_comm.sh -I netns_comm_ip_ipv6_ioctl netns_comm.sh -6I netns_comm_ns_exec_ipv4_netlink netns_comm.sh -e netns_comm_ns_exec_ipv6_netlink netns_comm.sh -6e netns_comm_ns_exec_ipv4_ioctl netns_comm.sh -eI netns_comm_ns_exec_ipv6_ioctl netns_comm.sh -6eI netns_sysfs netns_sysfs.sh shmnstest_none shmnstest -m none shmnstest_clone shmnstest -m clone shmnstest_unshare shmnstest -m unshare shmem_2nstest_none shmem_2nstest -m none shmem_2nstest_clone shmem_2nstest -m clone shmem_2nstest_unshare shmem_2nstest -m unshare shm_comm shm_comm mesgq_nstest_none mesgq_nstest -m none mesgq_nstest_clone mesgq_nstest -m clone mesgq_nstest_unshare mesgq_nstest -m unshare msg_comm msg_comm sem_nstest_none sem_nstest -m none sem_nstest_clone sem_nstest -m clone sem_nstest_unshare sem_nstest -m unshare semtest_2ns_none semtest_2ns -m none semtest_2ns_clone semtest_2ns -m clone semtest_2ns_unshare semtest_2ns -m unshare sem_comm sem_comm utsname01 utsname01 utsname02 utsname02 utsname03_clone utsname03 -m clone utsname03_unshare utsname03 -m unshare utsname04_clone utsname04 -m clone utsname04_unshare utsname04 -m unshare mountns01 mountns01 mountns02 mountns02 mountns03 mountns03 mountns04 mountns04 userns01 userns01 userns02 userns02 userns03 userns03 userns04 userns04 userns05 userns05 userns06 userns06 userns07 userns07 userns08 userns08 # time namespaces sysinfo03 sysinfo03 clock_nanosleep03 clock_nanosleep03 clock_gettime03 clock_gettime03 timens01 timens01 timerfd04 timerfd04
07-20

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值