我正在处理一项使用 IPC 方案通过共享文件在“服务器”和“客户端”之间进行通信的任务。
共享文件是在名为 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;
}
数据监视器(“客户端”)需要与此信号量保持联系,以确保它们不会同时交谈。我不确定客户端是否需要访问这个相同的信号量 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;
}