2016-07-03 20 views
1

現在、私はLinuxオペレーティングシステム用のC/C++プログラムを作っています。 名前付きパイプを使用して、2つのプログラム間でPID(プロセスID)を通信する必要があります。 パイプが作成され、ディレクトリに表示されます。名前付きパイプファイルディスクリプタ

Get PIDプログラムは、ファイル記述子が3を返しますが、パイプを開くことができる場合は0を返します。私は間違って何をしていますか?

はPIDが

// Several includes 
using namespace std; 

int main(int argc, char *argv[]) { 
    pid_t pid; 
    int sig = 22; 
    int succesKill; 
    int iFIFO; 
    char sPID[5] = {0,1,2,3,'\0'}; 
    iFIFO = open("IDpipe" , O_RDONLY); 
    if(iFIFO != 0) 
    { 
    cerr << "File descriptor does not return 0, but: " << iFIFO << endl; 
    return EXIT_FAILURE; 
    } 
    read(iFIFO, sPID, strlen(sPID)); 
    cerr << "In sPID now is: " << sPID << endl; 
    close(iFIFO); 
    pid = atoi(sPID); 
    cout << "The PID I will send signals to is: " << pid << "." << endl; 
    while(1) 
    { 
    succesKill = kill(pid, sig); 
    cout << "Tried to send signal" << endl; 
    sleep(5); 
    } 
    return EXIT_SUCCESS; 
} 

PID

// Several includes 
using namespace std; 

void catch_function(int signo); 

volatile sig_atomic_t iAmountSignals = 0; 

int main(void) { 
    pid_t myPID; 
    int iFIFO; 
    char sPID[5] = {'l','e','e','g','\0'}; 
    myPID = getpid(); 
    sprintf(sPID, "%d",myPID); 
    cout << "My PID is: " << sPID << endl; 
    iFIFO = open("IDpipe" , O_WRONLY); 
    if(iFIFO == -1) 
     { 
     cerr << "Pipe can't be opened for writing, error: " << errno << endl; 
     return EXIT_FAILURE; 
     } 
    write(iFIFO, sPID, strlen(sPID)); 
    close(iFIFO); 
    if (signal(22, catch_function) == SIG_ERR) { 
     cerr << "An error occurred while setting a signal handler." << endl; 
     return EXIT_FAILURE; 
    } 
    cout << "Raising the interactive attention signal." << endl; 
    if (raise(22) != 0) { 
     cerr << "Error raising the signal." << endl; 
     return EXIT_FAILURE; 
    } 
    while(1) 
    { 
     cout << "iAmountSignals is: " << iAmountSignals << endl; 
     sleep(1); 
    } 
    cout << "Exit." << endl; 
    return EXIT_SUCCESS; 
} 

void catch_function(int signo) { 
    switch(signo) { 
    case 22: 
     cout << "Caught a signal 22" << endl; 
     if(iAmountSignals == 9) 
      {iAmountSignals = 0;} 
     else 
      {++iAmountSignals;} 
     break; 
    default: 
     cerr << "Thats the wrong signal.." << endl; 
     break; 
    } 
} 

ターミナル出力を送るゲット

Output

答えて

0

あなたのロジックが間違っているようです。

if(iFIFO != 0) 

if(iFIFO == -1) 

openので戻り-1エラーであるべきです。それ以外の場合は、有効なファイル記述子を返します。

0

open()は、新しく作成されたファイルディスクリプタを返します。新しいプロセスが既にファイル記述子0を持っているという簡単な理由から、0を返すことはできません。これは標準入力になります。

3の戻り値は、open()からの予想される結果です。この場合、標準入力、出力、およびエラーの後で次に使用可能なファイル記述子であるためです。 open()がファイル記述子をオープンできなかった場合、-1を返します。

しかし、それ以外にも、あなたのコードは、他のバグの束を持っています

sprintf(sPID, "%d",myPID); 

// ... 

write(iFIFO, sPID, strlen(sPID)); 

あなたのプロセスIDが(可能である)長いだけで3桁​​の数字であることを起こる場合、これはパイプに3つのバイトを書き込みます。

プロセスIDが5桁の長さになる場合(これはさらに可能です)、これは5バイト長と '\ 0'バイトを合計して5バイト長のsPIDバッファに書き込まれます配列をオーバーランさせ、結果として未定義の動作を引き起こします。

実際の結果はもちろん、定義されていません、ですが、一般的なC++の実装では、スタック上の次の変数であるものは何でもの最初のバイトをつかうことになります、である:

あなたです
int iFIFO; 

ファイル記述子。あなたの運が無くなり、新しいプロセスが5桁のプロセスIDを取得し、これがリトルエンディアンのC++実装である場合、パディングはありません。iFIFOの下位バイトは0に設定され、コード最適化せずにコンパイルした場合、ファイル記述子iFIFOは0に設定されます。

さらに、パイプの反対側に:

char sPID[5] = {0,1,2,3,'\0'}; 

// ... 

read(iFIFO, sPID, strlen(sPID)); 

SPIDの最初のバイトは常に0に設定されているため、これは常にread(iFIFO, sPID, 0)を実行し、何も読んでいないだろう。その後

pid = atoi(sPID); 

atoi()は「\ 0'で終了する文字列を期待しています。 read()は読んだものだけを読み込みますが、読み終わるものは「\ 0」終了しません。 atoi()を使用する前に、読み込み入力を終了する '\ 0'を配置すること(そして、もちろん、読み込みバッファが十分に大きいことを確認すること)はあなたの責任です。

関連する問題