如何确定锁定posix信号量的进程的优先级?

时间:2016-08-16 15:27:28

标签: c linux semaphore

我有一个将数据写入共享内存的发布者进程。几个订阅者从共享内存中读取数据。我正在使用如下所示的posix信号量(简化以保持最小化)。 发布商代码:

var structuredData = [
    //These are your columns to add rows under, just add data to their arrays
  //['row1, 'row2', 'row3'] instead of the single row like it is now.
  ["cell1"],
  ["cell2"],
  ["cell3"],
  ["cell4"],
  ["cell5"],
  ["cell6"],
];

var visibleData = {
  list1: {
    element: document.getElementById('list1'),
    dataIndex: 0
  },
  list2: {
    element: document.getElementById('list1'),
    dataIndex: 1
  },
  list3: {
    element: document.getElementById('list1'),
    dataIndex: 2
  },
}

function refreshView() {
  var i;
  for (i = 1; i < 4; i++) { //using 1 intentionally.... coz it corresponds with the ID, loop however u want
    document.getElementById('list' + i).innerHTML = structuredData[visibleData['list' + i].dataIndex][0];
    //The 0 in the last bracket represents a ROW parameter, 
    //which since we are talking header is 0, same like
    //with the structured data array, each array inside is a column,
    //and the elements are row values, if you want to fill out a table,
    //make another loop within this one and circle through rows.
  }
}

refreshView();

function moveRight() {
  var i;
  for (i = 1; i < 3; i++) {
    visibleData['list' + i].dataIndex = visibleData['list' + (i+1)].dataIndex;
  }
  visibleData['list3'].dataIndex = visibleData['list2'].dataIndex + 1;
  if (!structuredData[visibleData['list3'].dataIndex]){
    //newColumn needs to be added to the right
    structuredData[visibleData['list3'].dataIndex] = ["cellNewAfter"];
  }
  refreshView();
}

function moveLeft() {
  var i;
  for (i = 3; i > 1; i--) {
    visibleData['list' + i].dataIndex = visibleData['list' + (i-1)].dataIndex;
  }
  visibleData['list1'].dataIndex = visibleData['list2'].dataIndex - 1;
  if (!structuredData[visibleData['list1'].dataIndex]){
    //newColumn needs to be added to the right
    structuredData[visibleData['list1'].dataIndex] = ["cellNewBefore"];
  }
  refreshView();
}

订户代码:

#include <fcntl.h>     //for flag O_CREAT, O_EXCL..
#include <sys/stat.h>  //for mode 0666
#include <semaphore.h> //for sem_open, sem_close, sem..
#include <stdio.h>     //for printf
#define MAX_READERS 100
int main()
{
    int i;
    //create the semaphore
    sem_t *sem = sem_open("AllHailMySemaphore", O_CREAT, 0666, MAX_READERS);
    //lock all the semaphores
    for(i=0; i<MAX_READERS; i++)
        sem_wait(sem);   //will this wait forever?
    //write to shared memory (skipped)
    //unlock all the semaphores
    for(i=0; i<MAX_READERS; i++)
        sem_post(sem);
    return 0;
}

只有1个发布者和100个订阅者;我怀疑发布者会在生产环境中饿死(必须永远等待锁定所有信号量)。有没有办法优先考虑出版商?

1 个答案:

答案 0 :(得分:0)

我正在回答我自己的问题。在一遍又一遍地阅读手册之后,这就是我想出的:

为了防止发布者进程出现饥饿,我可以使用另一个仅由发布者锁定的信号量。只有在发布者信号量解锁时,订阅者才会等待锁定。见下面的代码: 出版商:

#include <fcntl.h>     //for flag O_CREAT, O_EXCL..
#include <sys/stat.h>  //for mode 0666
#include <semaphore.h> //for sem_open, sem_close, sem..
#include <stdio.h>     //for printf
#define MAX_READERS 100
int main()
{
    int i;
    //create the semaphore
    sem_t *rsem = sem_open("ReaderSem", O_CREAT, 0666,
            MAX_READERS);
    sem_t *wsem = sem_open("WriterSem", O_CREAT, 0644,
            1);
    //lock the writer semaphore
    sem_wait(wsem);
    printf("writer semaphore locked. press enter to continue:");
    getchar();
    //lock all the reader semaphores
    for(i=0; i<MAX_READERS; i++)
        sem_wait(rsem);
    //unlock the writer semaphore
    sem_post(wsem);
    //write to shared memory (skipped)
    //unlock all the reader semaphores
    for(i=0; i<MAX_READERS; i++)
        sem_post(rsem);
    return 0;
}

订户代码:

#include <semaphore.h>
#include <stdio.h>
int main()
{
    sem_t *rsem = sem_open("ReaderSem", 0);    //get the reader sem
    sem_t *wsem = sem_open("WriterSem", 0);    //get the writer sem
    int wsem_val = 0;
    while(wsem_val<1){ //writer sem is locked
        sem_getvalue(wsem, &wsem_val);
        printf("writer sem val = %d\n", wsem_val);
        sleep(1);
    }
    sem_wait(rsem);   //consume 1 semaphore
    //read shared memory
    sem_post(rsem);   //release 1 semaphore
    return 0;
}

可能不推荐等待while循环。没有“等待零”&#39;在posix信号量中操作,但它有SystemV信号量。此外,SystemV信号量广泛可用。所以,我选择的是SystemV over Posix信号量。找到下面的systemV实现: 出版商:

#include <sys/sem.h>  //for systemV semaphores
#include <stdio.h>    //for printf and getchar
#include <stdlib.h>   //for malloc
#define MAX_READERS 100
int main()
{
    key_t key = (key_t)0xfeededdf; //any unique val. you could use ftok
    int semid = semget(key, 2,     //creates a semaphore set with 2 sems
            IPC_CREAT | IPC_EXCL | 0666);
    //initialize the sem.. note: creation and init is not atomic
    union semun {
        int val;
        struct semid_ds *buf;
        ushort *array;
    } arg;
    arg.array = (ushort*)malloc(sizeof(ushort)*2);
    arg.array[0] = 0;
    arg.array[1] = MAX_READERS;
    semctl(semid, 0, SETALL, arg);
    //end init
    printf("press enter to lock:");
    getchar();
    //lock the writer semaphore
    struct sembuf sb;
    sb.sem_num = 0;           //0th semaphore is writer
    sb.sem_op = 1;            //set it to 1
    sb.sem_flg = IPC_NOWAIT;  //should not have to wait
    semop(semid, &sb, 1);
    //end lock writer semaphore
    //lock all the reader semaphores
    sb.sem_num = 1;            //1th semaphore is reader
    sb.sem_op = -MAX_READERS;  //lock all together.. no loops
    sb.sem_flg = SEM_UNDO;     //undo this change when process terminates
    semop(semid, &sb, 1);
    //unlock the writer semaphore
    sb.sem_num = 0;           //0th semaphore is writer
    sb.sem_op = -1;           //make it 0
    sb.sem_flg = IPC_NOWAIT;  //should not have to wait
    semop(semid, &sb, 1);
    //end unlock writer
    //Write to shared memory (skipped)
    printf("press enter to unlock:");
    getchar();
    //unlock all the reader semaphores
    sb.sem_num = 1;           //1th semaphore is reader
    sb.sem_op = MAX_READERS;  //unlock all together
    sb.sem_flg = SEM_UNDO;    //undo this change when process terminates
    semop(semid, &sb, 1);
    printf("press enter to delete semaphore and exit:");
    getchar();
    semctl(semid, 0, IPC_RMID);
    return 0;
}

订阅者:

#include <stdio.h>      //for printf and getchar
#include <sys/sem.h>    //for systemV semaphores
int main()
{
    key_t key = (key_t)0xfeededdf;     //should use ftok instead
    int semid = semget(key, 0, 0);     //get the existing semaphore
    printf("press enter to lock reader semaphore:");
    getchar();
    struct sembuf sb[2];      //2 operations: 1.wait-for-writer 2.lock-reader
    sb[0].sem_num = 0;        //0th : writer semaphore
    sb[0].sem_op =  0;        //wait for zero
    sb[0].sem_flg = 0;        //don't need to undo
    sb[1].sem_num = 1;        //1th : reader semaphore
    sb[1].sem_op = -1;        //lock - decrement by 1
    sb[1].sem_flg = SEM_UNDO; //undo when process terminates
    semop(semid, sb, 2);      //2 denotes 2 operations (nsops=2)
    //read shared memory (skipped)
    printf("press enter to unlock reader semaphore and exit:");
    getchar();
    sb[0].sem_num = 1;        //1: reader sem. no need to wait for writer
    sb[0].sem_op  = 1;        //unlock: increment by 1
    sb[0].sem_flg = SEM_UNDO; //it might feel weird to undo the unlocking. but
                              //it is necessary. read about semadj structure.
    semop(semid, sb, 1);      //sb[1] will be ignored as nsops=1
    return 0;
}

来源:Stevens book

中的第15章(进程间通信)

P.S:我省略了返回值检查(错误)以保持代码较小。