2016-04-08 7 views
0

私は、共有ファイルを介して "サーバー"と "クライアント"の間で通信するためにIPCスキームを使用する割り当てに取り組んでいます。クライアントとサーバーを同じセマフォにリンクするにはどうすればいいですか

共有ファイルは、初期化されたセマフォとともにデータリーダーと呼ばれるサーバーアプリケーションで作成されます。このためのコードはここにある:

/* 
* 
* 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にアクセスする必要があるかどうか、またはこれらの2つのプロセスがセマフォーに一緒になるためのプロトコルは何かについてはわかりません。

データモニターのコードは以下の通りですが、クリティカルリージョンに入ることができず、サーバープロセスと正しく接続することもできません。

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

答えて

1

すべてのユーザがsemgetからすると全く同じkey(最初のパラメータを使用してsemget()のコールを実行する必要があるいくつかのプロセス間

セマフォを使用するため....一部はSystemVまたはPOSIX IPCコードであると思われます)。このkeyは、非常に同じセマフォインスタンスにアクセスするために、セマフォアクセスのすべての参加者の間で知る必要があるグローバル名のようなものです。

キーのために​​3210を使用すると、異なるプロセス間で共有されることはほとんどないユニークな(プライベート)セマフォが作成されます。

サーバーとクライアントの両方に共通のキーを定義して(int値を選択して)、両方のプロセスからsemget()を呼び出してください(実際には、他の誰にも分からないセマフォを取得することを目的としています)。 semopへのすべての呼び出し(返されたsamephoreIdを使用)は、セマフォーの同じインスタンスにアクセスします。

+0

他の引数はどうですか?サイズと旗?それらについて特別な何か?それはまだ私のために働いているようではありません –

+0

あなたが必要とするセマフォセマンティクスの種類に依存します。 – rpy

+1

普通のセマフォのほとんどの場合、nsemsの値は1になります。また、semflagsは新しいセマフォを作成するか、evtlが存在することを期待します。セマフォのアクセス権を設定して、セマフォにアクセスできる人をさらに制御する(セット)。 semget(およびPOSIXセマフォ)のマニュアルと一般的なセマフォに関するテキストブックを読んで、ニーズに合ったものをより明確に把握する必要があります。 – rpy

関連する問題