C语言 信号量问题

kpbwa7wx  于 2023-06-21  发布在  其他
关注(0)|答案(1)|浏览(173)

为了练习信号量我写了一些基本的代码来理解这个概念
服务器代码如下

#include "MySem.h"
#include "MyShm.h"
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/types.h>

void signalHandler(int signum);

int shmid = 0;
int *shmaddr = 0;

int semidServ = 0;
int semidClnt = 0;

int main(int argc, char const *argv[]) {
    int req = 0;
    int res = 0;

    union semun semunBuf;
    shmid = createShm(MY_SHM_KEY);
    shmaddr = shmat(shmid, NULL, 0);

    semidServ = creatSem(MY_SEM_SERV_KEY);
    semunBuf.val = 0;
    semctl(semidServ, 0, SETVAL, semunBuf);

    semidClnt = creatSem(MY_SEM_CLNT_KEY);
    semunBuf.val = 1;
    semctl(semidClnt, 0, SETVAL, semunBuf);

    signal(SIGINT, signalHandler);

    while (1) {
        puts("Wait ...");

        lockSem(semidServ);
        memcpy(&req, shmaddr, sizeof(int));
        res = req + 1;
        memcpy(shmaddr, &res, sizeof(int));
        unlockSem(semidClnt);

        printf("Request: %d\n", req);
        printf("Response: %d\n", res);
        fflush(stdout);
    }

    return 0;
}

客户端代码是这样的

#include "MySem.h"
    #include "MyShm.h"
    #include <signal.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/sem.h>
    #include <sys/shm.h>
    #include <sys/types.h>
    
    void signalHandler(int signum);
    
    int shmid = 0;
    int *shmaddr = NULL;
    
    int semidServ = 0;
    int semidClnt = 0;
    
    int main(int argc, char const *argv[]) {
        int req = 0;
        int res;
    
        shmid = openShm(MY_SHM_KEY);
        shmaddr = shmat(shmid, NULL, 0);
    
        semidServ = openSem(MY_SEM_SERV_KEY);
        semidClnt = openSem(MY_SEM_CLNT_KEY);
    
        signal(SIGINT, signalHandler);
    
        while (1) {
            printf("<<");
            scanf("%d", &req);
            fflush(stdout);
            fflush(stdin);
    
            lockSem(semidClnt);
            memcpy(shmaddr, &req, sizeof(int));
            unlockSem(semidServ);
    
            lockSem(semidClnt);
            memcpy(&res, shmaddr, sizeof(int));
            unlockSem(semidClnt);
    
            printf(">> %d\n", res);
        }
        return 0;
    }

我想知道的是,在scanf函数之后的客户端代码中,两个信号量都被lockSem(semidClnt)锁定为值0;服务器和客户端之间的通信仍然有效吗?我对这段代码有什么误解吗?

c8ib6hqw

c8ib6hqw1#

我不清楚你在问什么。我认为你只是想让我们重新检查代码。
这很好,但我会简化客户端。
首先,信号量不能被锁定。您可以使用信号量作为互斥量,但您没有这样做。因此,在这里将信号量称为被锁定是没有意义的。
在我的简化版本中,我还将使用两个信号量。

  • request_sem,它有两种状态:

| 状态|意义|初始|
| - -----|- -----|- -----|
| 0|没有待处理的请求。|初始状态。|
| 1|请求待定。||
request_semsemidServ的新名称。

  • response_sem,它有两种状态:

| 状态|意义|初始|
| - -----|- -----|- -----|
| 0|没有答复。|初始状态。|
| 1|响应准备就绪。||
response_sem替换了semidClnt。它与原始程序中的semidClnt具有完全不同的状态,并且具有不同的初始状态。描述semidClnt的状态非常复杂,这是一个可以改进的明确指标。
服务器代码保持不变(除了名称)。

// Wait for a request to come in (wait for `request_sem` to be 1).
// Indicate no request is pending (set `request_sem` to 0).
// `response_sem` is expected to be 0 when this returns
// so that we can set it to 1 when the response is ready.
sem_wait(request_sem);

// Service the request.
memcpy(&req, shmaddr, sizeof(int));
res = req + 1;
memcpy(shmaddr, &res, sizeof(int));

// Indicate the response is ready (set `response_sem` to 1).
sem_post(response_sem);

简化了客户端代码。

// `request_sem` is expected to be 0 here.
// `response_sem` is expected to be 0 here.

req = ...;

// Send request.
memcpy(shmaddr, &req, sizeof(int));

// Let the server know a request was made (set `request_sem` to 1).
sem_post(request_sem);

// Wait for a response to come in (wait for `response_sem` to be 1).
// Indicate no response is pending (set `response_sem` to 0).
// `request_sem` is expected to be 0 when this returns
// so that we can set it to 1 when we make our next request.
sem_wait(response_sem);

// Receive response.
memcpy(&res, shmaddr, sizeof(int));

我们可以很容易地验证我们的假设(“X被期望为Y”),并看到这段代码工作正常,同时简单得多。

相关问题