2016-04-08 7 views
0

Ich arbeite an einer Zuweisung, die IPC-Schemata verwendet, um zwischen "Server" und einem "Client" über freigegebene Dateien zu kommunizieren.Wie verbinde ich Client und Server mit dem gleichen Semaphor

Die freigegebene Datei wird in der Serveranwendung mit dem Namen Data Reader zusammen mit einem Semaphor erstellt, der initialisiert wird. Der Code dafür ist hier:

/* 
* 
* 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; 
} 

Datenmonitor („Kunde“) muss mit diesen Semaphore in Kontakt benutzen, um sicherzustellen, dass sie nie zur gleichen Zeit sprechen. Ich bin nicht sicher, ob der Client Zugriff auf die gleiche Semaphor-ID haben muss, oder welches Protokoll diese beiden Prozesse in einem Semaphor zusammen haben sollen.

Der Code für den Datenmonitor ist unten, und es ist nicht in der Lage, die kritische Region einzugeben, noch glaube ich, dass es eine korrekte Verbindung mit dem Serverprozess herstellen wird.

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 (&currentTime); 
        timeinfo = localtime (&currentTime); 

        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 (&currentTime); 
        timeinfo = localtime (&currentTime); 

        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; 
     } 

Antwort

1

Scheint einige SystemV oder POSIX IPC-Code zu sein ....

Für muss jeder Benutzer eine Semaphore unter mehreren Prozessen unter Verwendung eines Anrufs auf semget() mit dem gleichen key (erster Parameter ausführen semget). Diese key ist eine Art globaler Name, der unter allen Teilnehmern des Semaphor-Zugriffs bekannt sein muss (und geteilt werden muss), um Zugang zu derselben Semaphor-Instanz zu erhalten.

Mit IPC_PRIVATE für den Schlüssel, wie Sie tun, wird ein eindeutiger (private) Semaphor, der sehr unwahrscheinlich ist, unter den verschiedenen Prozessen geteilt werden. (Der eigentliche Zweck besteht darin, ein Semaphor zu erhalten, das niemandem bekannt ist.)

Also einen gemeinsamen Schlüssel für Ihren Server und Ihren Client (wählen Sie einen int-Wert) und rufen Sie semget() von beiden Prozessen. Dann greifen alle Aufrufe an semop (unter Verwendung der zurückgegebenen Funktion samephoreId) auf dieselbe Instanz des Semaphors zu.

+0

Was ist mit den anderen Argumenten? Die Größe und die Flaggen? Irgendwas Besonderes an denen? Es scheint immer noch nicht für mich zu arbeiten –

+0

Je nachdem, welche Art von Semaphor Semantik Sie benötigen. – rpy

+1

In den meisten Fällen für einfache Semaphore ist ein Nsems-Wert von 1 in Ordnung, und die SemFlags werden gesetzt, um einen neuen Semaphor zu erzeugen oder zu erwarten, dass einer existiert und ggf.. Legen Sie die Berechtigungen für den Semaphor fest, um festzulegen, wer auf den Semaphor zugreifen darf (set). Sie sollten das Handbuch zu semget (und POSIX-Semaphoren) und einige Lehrbücher zu Semaphoren lesen, um ein klareres Bild davon zu bekommen, was Ihren Bedürfnissen entspricht. – rpy

Verwandte Themen