请教UXIN系统中信号量是如何绑定共享内存的?

时间:2022-04-01 15:14:01
我们都知道进程是通过获取信号量来访问共享内存的,但是操作系统又如何知道信号量是控制哪个共享内存的,这个是由程序来实现的还是由操作系统来控制的?如果是由程序来实现的,那又是怎么做的呢?

12 个解决方案

#1


程序实现的吧
要想用共享内存,要先获取信号量,否则就挂起
用完内存后,释放信号量,以便别的进程得以运行

#2


我的理解是用程序吧。
比方说某人(A进程)有个保险箱(信号量),他用保险箱存金条(或者可乐也行,共享内存,防止金条被小偷(B进程)偷走),具体保险箱里保存什么应该是由人(A进程)来决定的吧。
不知道举的例子有没有问题啊

#3


如果是由程序来实现的,岂不是设一个全局变量flag就可以了,flag大于0就表示共享内存可用,否则就不可用,干吗还用信号量这么费事?应该没这么简单吧?

#4


当然是有操作系统实现了 

#5


信号量 -> semaphore?它与 shm 是独立的,只是程序之间的一种约定。譬如
sem_t -> @/app1/sem1
shm   -> /dev/shm/app1_shm1

两个程序约定,只有当获取了 @/app1/sem1 的时候才能操作 /dev/shm/app1_shm1
就这么回事。至于这两个东西是不是必须在物理上有所关联,答案是否定的。


----

到不如 mmap 一个文件,然后用 flock / futex 去缩这个文件 / 内存块的某个 byte 来的精简

#6


》》 3楼

如果真的那么简单,那些研究同步理论的人不都在自己给自己找麻烦。
你要考虑到分时系统上程序在运行中被中断的情况,相关的书籍不是一般的多。

#7


各位高人,你们可能还没明白我问题的意思,关于信号量与共享内存之间的pv操作,这些基本的理论我都懂,相信也有很多资料对此进行了详细的介绍。我想知道的是,信号量是通过何种方式与指定的共享内存联系的?即程序是如何知道我建立的信号量是控制哪一块共享内存的?不知道我说明白没?

#8


did you see my reply?

#9


Wolf0403兄说得很清楚了。

信号量和共享内存没有任何既定的联系,它们都是操作系统提供的进程间通信方式,不过信号量是互斥的而已。lz所谓信号量和共享内存间的联系,是应用程序为了利用信号量的互斥特性保证共享内存并发访问的安全而利用定义的,只是逻辑上的联系,而非物理的。具体哪个信号量标识哪段共享内存除了应用程序的设计者没有人知道。

#10


解释的很明白。但我还有一个问题,既然信号量标识哪段共享内存是由程序来实现的,那在程序里具体要怎么做呢?

#11


在访问共享内存前,首先试图去获得一个信号量旗标。如果成功,本进/线程就获得了对共享内存的访问权,在释放信号量旗标前其他进/线程无法获得该旗标,接下来本过程就可以对内存进行读写等操作。在共享内存使用完毕后,本进/线程释放旗标,其他进/线程又可以成功获取该信号量旗标。下面是简单的例子(程序中的函数和结构等请自己查手册):

iSemID = semget(SEMKEY, 1, S_IRUSR | S_IWUSR);  //获取信号量
if(iSemID != -1) {
    tSops.sem_num = 0;
    tSops.sem_op  = -(PROCESS_MAX);
    tSops.sem_flg = 0;
    iRc = semop(iSemID, &tSops, 1);
    if(iRc == -1) {
        printf("semop(ON) failed.");   //信号量操作失败
    }
    tSops.sem_op = 0 - tSops.sem_op;
} else {
    printf("semget failed.");   //获取信号量失败
}

iShmID = shmget(MEMKEY, sizeof(....), S_IRUSR | S_IWUSR);  //获取共享内存
if(iShmID != -1){
    pStruct = (... *)shmat(iShmID, NULL, 0);
    if(pStruct == SHM_FAILED){
        printf("shmat failed.");  //映射共享内存失败
    }
}else{
    printf("shmget failed."); //获取共享内存失败
}

........  //程序逻辑

iRc = shmdt(pStruct);  //取消共享内存映射
if(iRc == -1){
    sprintf("shmdt failed.");  //取消共享内存映射失败
}

iRc = semop(iSemID, &tSops, 1); //释放信号量
if(iRc == -1){
    sprintf("semop(OFF) failed.");  //释放信号量失败
}

实际上系统提供的任一互斥机制都可以和某种资源组合,将对这一资源的访问描述为互斥的,而不仅仅是上述的信号量和共享内存一种情况。

#12


多谢多谢,非常明白!

#1


程序实现的吧
要想用共享内存,要先获取信号量,否则就挂起
用完内存后,释放信号量,以便别的进程得以运行

#2


我的理解是用程序吧。
比方说某人(A进程)有个保险箱(信号量),他用保险箱存金条(或者可乐也行,共享内存,防止金条被小偷(B进程)偷走),具体保险箱里保存什么应该是由人(A进程)来决定的吧。
不知道举的例子有没有问题啊

#3


如果是由程序来实现的,岂不是设一个全局变量flag就可以了,flag大于0就表示共享内存可用,否则就不可用,干吗还用信号量这么费事?应该没这么简单吧?

#4


当然是有操作系统实现了 

#5


信号量 -> semaphore?它与 shm 是独立的,只是程序之间的一种约定。譬如
sem_t -> @/app1/sem1
shm   -> /dev/shm/app1_shm1

两个程序约定,只有当获取了 @/app1/sem1 的时候才能操作 /dev/shm/app1_shm1
就这么回事。至于这两个东西是不是必须在物理上有所关联,答案是否定的。


----

到不如 mmap 一个文件,然后用 flock / futex 去缩这个文件 / 内存块的某个 byte 来的精简

#6


》》 3楼

如果真的那么简单,那些研究同步理论的人不都在自己给自己找麻烦。
你要考虑到分时系统上程序在运行中被中断的情况,相关的书籍不是一般的多。

#7


各位高人,你们可能还没明白我问题的意思,关于信号量与共享内存之间的pv操作,这些基本的理论我都懂,相信也有很多资料对此进行了详细的介绍。我想知道的是,信号量是通过何种方式与指定的共享内存联系的?即程序是如何知道我建立的信号量是控制哪一块共享内存的?不知道我说明白没?

#8


did you see my reply?

#9


Wolf0403兄说得很清楚了。

信号量和共享内存没有任何既定的联系,它们都是操作系统提供的进程间通信方式,不过信号量是互斥的而已。lz所谓信号量和共享内存间的联系,是应用程序为了利用信号量的互斥特性保证共享内存并发访问的安全而利用定义的,只是逻辑上的联系,而非物理的。具体哪个信号量标识哪段共享内存除了应用程序的设计者没有人知道。

#10


解释的很明白。但我还有一个问题,既然信号量标识哪段共享内存是由程序来实现的,那在程序里具体要怎么做呢?

#11


在访问共享内存前,首先试图去获得一个信号量旗标。如果成功,本进/线程就获得了对共享内存的访问权,在释放信号量旗标前其他进/线程无法获得该旗标,接下来本过程就可以对内存进行读写等操作。在共享内存使用完毕后,本进/线程释放旗标,其他进/线程又可以成功获取该信号量旗标。下面是简单的例子(程序中的函数和结构等请自己查手册):

iSemID = semget(SEMKEY, 1, S_IRUSR | S_IWUSR);  //获取信号量
if(iSemID != -1) {
    tSops.sem_num = 0;
    tSops.sem_op  = -(PROCESS_MAX);
    tSops.sem_flg = 0;
    iRc = semop(iSemID, &tSops, 1);
    if(iRc == -1) {
        printf("semop(ON) failed.");   //信号量操作失败
    }
    tSops.sem_op = 0 - tSops.sem_op;
} else {
    printf("semget failed.");   //获取信号量失败
}

iShmID = shmget(MEMKEY, sizeof(....), S_IRUSR | S_IWUSR);  //获取共享内存
if(iShmID != -1){
    pStruct = (... *)shmat(iShmID, NULL, 0);
    if(pStruct == SHM_FAILED){
        printf("shmat failed.");  //映射共享内存失败
    }
}else{
    printf("shmget failed."); //获取共享内存失败
}

........  //程序逻辑

iRc = shmdt(pStruct);  //取消共享内存映射
if(iRc == -1){
    sprintf("shmdt failed.");  //取消共享内存映射失败
}

iRc = semop(iSemID, &tSops, 1); //释放信号量
if(iRc == -1){
    sprintf("semop(OFF) failed.");  //释放信号量失败
}

实际上系统提供的任一互斥机制都可以和某种资源组合,将对这一资源的访问描述为互斥的,而不仅仅是上述的信号量和共享内存一种情况。

#12


多谢多谢,非常明白!