我如何 link 客户端和服务器到同一个信号量
How do I link client and server to the same semaphore
我正在进行一项作业,该作业使用 IPC 方案在 "Server" 和 "Client" 之间通过共享文件进行通信。
共享文件是在名为 Data Reader 的服务器应用程序中创建的,同时还有一个已初始化的信号量。代码在这里:
/*
*
* Function Name: initializeSemaphores()
* Description: This function initializes the semaphoreID and sets initial values for
* the semaphore.
*
* Parameters: void.
* Returns: semaphoreID (pid_t) = The semaphore ID of the semaphore we initialized.
*/
pid_t initializeSemaphore(void)
{
pid_t semaphoreID = -1;
semaphoreID = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666);
if(semaphoreID == -1)
{
printf("(SERVER) Cannot create semaphore.\n");
logErrorStatus("Cannot create semaphore.", __FILE__, __LINE__);
}
printf("(SERVER) Semaphore ID is: %d\n", semaphoreID);
//Initialize semaphore to a known value
if(semctl(semaphoreID, 0, SETALL, init_values) == -1)
{
printf("(SERVER) Cannot initialize semaphores.\n");
logErrorStatus("Cannot initialize semaphores.", __FILE__, __LINE__);
semaphoreID = -1;
}
return semaphoreID;
}
/*
* Function Name: writeToSharedFile
* Description: Write machineID and status code to the shared file using semaphore control.
*
* Parameters: semaphoreID (pid_t) = The id of the semaphore we are using to communicate
* machineID (pid_t) = The id of the DataCreator to be written to the shared file.
* statusCode (int) = The status code to be written to the shared file.
* Returns: success (int) = Success code.
*/
int writeToSharedFile(pid_t semaphoreID, pid_t machineID, int statusCode)
{
int success = kNoError;
FILE* sharedFilePointer = NULL;
//Enter the critical region (gain access to the "talking stick")
if(semop (semaphoreID, &acquire_operation, 1) == -1)
{
printf("(SERVER) Cannot start critical region\n");
logErrorStatus("Cannot start critical region", __FILE__, __LINE__);
success = kCriticalRegionError;
}
//Open the shared file for appending in binary
if((sharedFilePointer = fopen(kSharedFile, "ab+")) == NULL)
{
printf("(SERVER) Cannot write to shared file.\n");
logErrorStatus("Cannot write to shared file.", __FILE__, __LINE__);
success = kSharedFileError;
}
//Write the machineID and statusCode to the shared file
fwrite(&machineID, sizeof(int), 1, sharedFilePointer);
fwrite(&statusCode, sizeof(int), 1, sharedFilePointer);
//Exit the critical region (make access to the "talking stick" available to use)
if(semop(semaphoreID, &release_operation, 1) == -1)
{
printf("(SERVER) Cannot exit critical region.\n");
logErrorStatus("Cannot exit critical region.", __FILE__, __LINE__);
success = kCriticalRegionError;
}
//Close the shared file
if(fclose(sharedFilePointer) != 0)
{
printf("(SERVER) Cannot close shared file.\n");
logErrorStatus("Cannot close shared file.", __FILE__, __LINE__);
success = kSharedFileError;
}
return success;
}
数据监视器 ("Client") 需要使用与此信号量的联系,以确保它们不会同时通话。我不确定客户端是否需要访问相同的信号量 ID,或者这两个进程一起位于信号量中的协议是什么?
数据监控的代码如下,无法进入临界区,我认为也不能正确连接服务器进程。
if(FindSharedFile())
{
while (1)
{
usleep(500000);
// attempt to set initial semaphore flag for dr
if (semop (semID, &acquire_operation, 1) == -1)
{
printf ("Cannot start critical region\n");
break;
}
if ((filePointer = fopen (kNameOfSharedFile, "rb")) != NULL)
{
if(fgets (data, sizeof (data), filePointer) != NULL)
{
printf ("DataMonitor Received data from DataReader ... <%s>\n", data);
previousMachineID = machineID;
previousStatusCode = statusCode;
// seek to end and use pointer arithmetic to calculate
// how many bytes we want to read at a time
fseek(filePointer, SEEK_END - (sizeof(int) * 2), 0);
// read data
fread(&machineID, sizeof(int), 1, filePointer);
printf("Machine id: %d\n", machineID);
fread(&statusCode, sizeof(int), 1, filePointer);
printf("Status Code: %d\n", statusCode);
// check if machine has gone off line
if(machineID == 0x00000000 || statusCode == 0xFFFFFFFF)
{
// get time stamp
time_t currentTime;
struct tm* timeinfo;
time ( ¤tTime );
timeinfo = localtime ( ¤tTime );
char* subject = "Server Has Gone Offline\n";
char* message = "";
sprintf(message, "DC Machine ID: %d \nStatus Reported: %s \nStatus Effective: %s \n", machineID, GetStatusCode(statusCode), asctime(timeinfo));
// if the email sent succesfully, break out of loop and continue to clean up environment
if(SendEmail(kNameOfSender, kNameOfRecipent, subject, message) == 0)
{
break;
}
}
if(machineID != previousMachineID && statusCode != previousStatusCode)
{
// get time stamp
time_t currentTime;
struct tm* timeinfo;
time ( ¤tTime );
timeinfo = localtime ( ¤tTime );
char* subject = "Update Status for Machine ID: ";
sprintf(subject, "Update Status for Machine ID: %d", machineID);
char* message = "";
sprintf(message, "DC Machine ID: %d \nStatus Reported: %s \nStatus Effective: %s \n", machineID, GetStatusCode(statusCode), asctime(timeinfo));
if(SendEmail(kNameOfSender, kNameOfRecipent, subject, message) == 0)
{
continue;
}
}
}
fclose (filePointer);
}
// attempt to change semaphore status
if (semop (semID, &release_operation, 1) == -1)
{
printf ("DM can't end critical region\n");
break;
}
似乎是一些 SystemV 或 POSIX IPC 代码....
要在多个进程中使用信号量,每个用户都需要使用相同的 key
(semget 的第一个参数)对 semget()
执行调用。这个 key
是一种全局名称,需要在信号量访问的所有参与者之间知道(和共享)才能访问同一个信号量实例。
像您一样使用 IPC_PRIVATE
作为密钥将创建一个唯一的(私有)信号量,该信号量不太可能在不同进程之间共享。 (其实目的是得到一个别人不知道的信号量。)
因此为您的服务器和客户端定义了一个公共键(选择一些 int 值)并从两个进程调用 semget()
。然后所有对 semop
的调用(使用返回的 samephoreId)将访问信号量的相同实例。
我正在进行一项作业,该作业使用 IPC 方案在 "Server" 和 "Client" 之间通过共享文件进行通信。
共享文件是在名为 Data Reader 的服务器应用程序中创建的,同时还有一个已初始化的信号量。代码在这里:
/*
*
* Function Name: initializeSemaphores()
* Description: This function initializes the semaphoreID and sets initial values for
* the semaphore.
*
* Parameters: void.
* Returns: semaphoreID (pid_t) = The semaphore ID of the semaphore we initialized.
*/
pid_t initializeSemaphore(void)
{
pid_t semaphoreID = -1;
semaphoreID = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666);
if(semaphoreID == -1)
{
printf("(SERVER) Cannot create semaphore.\n");
logErrorStatus("Cannot create semaphore.", __FILE__, __LINE__);
}
printf("(SERVER) Semaphore ID is: %d\n", semaphoreID);
//Initialize semaphore to a known value
if(semctl(semaphoreID, 0, SETALL, init_values) == -1)
{
printf("(SERVER) Cannot initialize semaphores.\n");
logErrorStatus("Cannot initialize semaphores.", __FILE__, __LINE__);
semaphoreID = -1;
}
return semaphoreID;
}
/*
* Function Name: writeToSharedFile
* Description: Write machineID and status code to the shared file using semaphore control.
*
* Parameters: semaphoreID (pid_t) = The id of the semaphore we are using to communicate
* machineID (pid_t) = The id of the DataCreator to be written to the shared file.
* statusCode (int) = The status code to be written to the shared file.
* Returns: success (int) = Success code.
*/
int writeToSharedFile(pid_t semaphoreID, pid_t machineID, int statusCode)
{
int success = kNoError;
FILE* sharedFilePointer = NULL;
//Enter the critical region (gain access to the "talking stick")
if(semop (semaphoreID, &acquire_operation, 1) == -1)
{
printf("(SERVER) Cannot start critical region\n");
logErrorStatus("Cannot start critical region", __FILE__, __LINE__);
success = kCriticalRegionError;
}
//Open the shared file for appending in binary
if((sharedFilePointer = fopen(kSharedFile, "ab+")) == NULL)
{
printf("(SERVER) Cannot write to shared file.\n");
logErrorStatus("Cannot write to shared file.", __FILE__, __LINE__);
success = kSharedFileError;
}
//Write the machineID and statusCode to the shared file
fwrite(&machineID, sizeof(int), 1, sharedFilePointer);
fwrite(&statusCode, sizeof(int), 1, sharedFilePointer);
//Exit the critical region (make access to the "talking stick" available to use)
if(semop(semaphoreID, &release_operation, 1) == -1)
{
printf("(SERVER) Cannot exit critical region.\n");
logErrorStatus("Cannot exit critical region.", __FILE__, __LINE__);
success = kCriticalRegionError;
}
//Close the shared file
if(fclose(sharedFilePointer) != 0)
{
printf("(SERVER) Cannot close shared file.\n");
logErrorStatus("Cannot close shared file.", __FILE__, __LINE__);
success = kSharedFileError;
}
return success;
}
数据监视器 ("Client") 需要使用与此信号量的联系,以确保它们不会同时通话。我不确定客户端是否需要访问相同的信号量 ID,或者这两个进程一起位于信号量中的协议是什么?
数据监控的代码如下,无法进入临界区,我认为也不能正确连接服务器进程。
if(FindSharedFile())
{
while (1)
{
usleep(500000);
// attempt to set initial semaphore flag for dr
if (semop (semID, &acquire_operation, 1) == -1)
{
printf ("Cannot start critical region\n");
break;
}
if ((filePointer = fopen (kNameOfSharedFile, "rb")) != NULL)
{
if(fgets (data, sizeof (data), filePointer) != NULL)
{
printf ("DataMonitor Received data from DataReader ... <%s>\n", data);
previousMachineID = machineID;
previousStatusCode = statusCode;
// seek to end and use pointer arithmetic to calculate
// how many bytes we want to read at a time
fseek(filePointer, SEEK_END - (sizeof(int) * 2), 0);
// read data
fread(&machineID, sizeof(int), 1, filePointer);
printf("Machine id: %d\n", machineID);
fread(&statusCode, sizeof(int), 1, filePointer);
printf("Status Code: %d\n", statusCode);
// check if machine has gone off line
if(machineID == 0x00000000 || statusCode == 0xFFFFFFFF)
{
// get time stamp
time_t currentTime;
struct tm* timeinfo;
time ( ¤tTime );
timeinfo = localtime ( ¤tTime );
char* subject = "Server Has Gone Offline\n";
char* message = "";
sprintf(message, "DC Machine ID: %d \nStatus Reported: %s \nStatus Effective: %s \n", machineID, GetStatusCode(statusCode), asctime(timeinfo));
// if the email sent succesfully, break out of loop and continue to clean up environment
if(SendEmail(kNameOfSender, kNameOfRecipent, subject, message) == 0)
{
break;
}
}
if(machineID != previousMachineID && statusCode != previousStatusCode)
{
// get time stamp
time_t currentTime;
struct tm* timeinfo;
time ( ¤tTime );
timeinfo = localtime ( ¤tTime );
char* subject = "Update Status for Machine ID: ";
sprintf(subject, "Update Status for Machine ID: %d", machineID);
char* message = "";
sprintf(message, "DC Machine ID: %d \nStatus Reported: %s \nStatus Effective: %s \n", machineID, GetStatusCode(statusCode), asctime(timeinfo));
if(SendEmail(kNameOfSender, kNameOfRecipent, subject, message) == 0)
{
continue;
}
}
}
fclose (filePointer);
}
// attempt to change semaphore status
if (semop (semID, &release_operation, 1) == -1)
{
printf ("DM can't end critical region\n");
break;
}
似乎是一些 SystemV 或 POSIX IPC 代码....
要在多个进程中使用信号量,每个用户都需要使用相同的 key
(semget 的第一个参数)对 semget()
执行调用。这个 key
是一种全局名称,需要在信号量访问的所有参与者之间知道(和共享)才能访问同一个信号量实例。
像您一样使用 IPC_PRIVATE
作为密钥将创建一个唯一的(私有)信号量,该信号量不太可能在不同进程之间共享。 (其实目的是得到一个别人不知道的信号量。)
因此为您的服务器和客户端定义了一个公共键(选择一些 int 值)并从两个进程调用 semget()
。然后所有对 semop
的调用(使用返回的 samephoreId)将访问信号量的相同实例。