信号量在 C 中无法正常工作的问题



我目前正在尝试制作一个客户端/服务器程序。服务器需要防止错误在同一时间接收多个消息。

下面是server.c代码:

#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <sys/sem.h>
#include <time.h>
#include <semaphore.h>
typedef struct {
long id;
char mes[20];
} message;
double calculate(int num){
return num*2;
}
struct sembuf semaphore_operations[1];
int main() {

// key
key_t cle = ftok(".", 0);
if (cle == -1) {
perror("ftok");
return -1;
}
// message queue
int msqId = msgget(cle, IPC_CREAT | 0700);
if (msqId == -1) {
perror("msgget");
return -1;
}
// semaphore
int semId = semget(cle, 1, IPC_CREAT | 0700);
if (semId == -1) {
perror("semget");
return -1;
}
if (semctl(semId, 0, SETVAL, 1) == -1) {
perror("semctl");
return -1;
}
semaphore_operations[0].sem_num = 0;
semaphore_operations[0].sem_flg = 0;
message mes;
while (1) {

semaphore_operations[0].sem_op = -1;
if (semop(semId, semaphore_operations, 1) == -1) {
perror("semop");
return -1;
}
// wait for message (blocked)
int received = msgrcv(msqId, &mes, sizeof(message) - sizeof(long), 0, 0);
if (received == -1) {
perror("msgrcv");
return -1;
}
int num_mat = atoi(mes.mes);
printf("Server: message received :%d.n", num_mat);
if(num_mat > 0) {
double result = calculate(num_mat);
char result_str[20] = "";
sprintf(result_str, "%f", result);
strcpy(mes.mes, result_str);
int sent = msgsnd(msqId, &mes, sizeof(message) - sizeof(long), 0);
if (sent == -1) {
perror("msgsnd");
return -1;
}
printf("Server: message sent.n");
}
else {
strcpy(mes.mes, "Invalid number");
int sent = msgsnd(msqId, &mes, sizeof(message)-sizeof(long), 0);

if(sent == -1){
perror("msgsnd");
return -1;
}
}

// signal the semaphore
semaphore_operations[0].sem_op = 1;
if (semop(semId, semaphore_operations, 1) == -1) {
perror("semop");
return -1;
}
}
// remove when server shut down
msgctl(msqId, IPC_RMID, NULL);
semctl(semId, 0, IPC_RMID, 0);
return 0;
}

下面是cli_test.c同时发送两条消息:

#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <sys/sem.h>
#include <time.h>
#include <semaphore.h>
#include <pthread.h>
typedef struct {
long id;
char mes[20];
} message;
void* client_thread(void* arg) {

key_t cle = ftok(".", 0);
if (cle == -1) {
perror("ftok");
pthread_exit(NULL);
}
int msqId = msgget(cle, 0);
if (msqId == -1) {
perror("msgget");
pthread_exit(NULL);
}
message mes;
mes.id = 1;
int num = *((int*) arg);
sprintf(mes.mes, "%d", num);
// send message to the server
int sent = msgsnd(msqId, &mes, sizeof(message) - sizeof(long), 0);
if (sent == -1) {
perror("msgsnd");
pthread_exit(NULL);
}
// receive the result
message result;
int received = msgrcv(msqId, &result, sizeof(message) - sizeof(long), 0, 0);
if (received == -1) {
perror("msgrcv");
pthread_exit(NULL);
}

printf("Client: message received :%s.n", result.mes);
pthread_exit(NULL);
}
int main() {

pthread_t client1, client2;
int num1 = 10, num2 = -1;
if (pthread_create(&client1, NULL, client_thread, &num1) != 0) {
perror("pthread_create");
return -1;
}
if (pthread_create(&client2, NULL, client_thread, &num2) != 0) {
perror("pthread_create");
return -1;
}
pthread_join(client1, NULL);
pthread_join(client2, NULL);
return 0;
}

服务器似乎没有工作,因为cli_test的输出是:

Client: message received :20.000000.
Client: message received :-1.

期望的输出应该是:

Client: message received :20.000000.
Client: message received :Invalid number.

将num1改为-12,num2改为-1,

Client: message received :-1.
Client: message received :Invalid number.

期望的输出应该是:

Client: message received :Invalid number.
Client: message received :Invalid number.

将num1改为12,num2改为1,

Client: message received :24.000000.
Client: message received :1.000000.

期望的输出应该是:

Client: message received :24.000000.
Client: message received :2.000000.

它似乎工作了一半,它只计算一个数字,另一个不计算,只是发送给客户端返回…

仅由一个任务(进程、线程)使用的信号量是没有意义的。都是错的。

如果你只是移除信号量代码,你的程序就能正常工作。

Client: message received :10.000000.
Client: message received :Invalid number.

最新更新