簡體   English   中英

命名管道文件描述符

[英]Named pipe file descriptor

目前我正在為Linux操作系統制作一個C / C ++程序。 我想使用命名管道在兩個程序之間傳遞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;
    }
}

終端輸出

產量

您的邏輯似乎不正確。

if(iFIFO != 0)

應該

if(iFIFO == -1)

因為open錯誤時返回-1。 否則返回有效的文件描述符。

open()返回新創建的文件描述符。 由於新進程已經具有文件描述符0的簡單原因,它不能返回0.這將是標准輸入。

返回值3是open()的預期結果,在這種情況下,因為它將是標准輸入,輸出和錯誤之后的下一個可用文件描述符。 如果open()無法打開文件描述符,則返回-1。

但除此之外,您的代碼還有一堆其他錯誤:

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

// ...

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

如果您的進程ID恰好只有3位數(這是可能的),這將寫入三個字節到管道。

如果您的進程ID恰好是五位數(甚至更可能),這將寫入5個字節加上'\\ 0'字節,總共六個字節寫入五個字節長的sPID緩沖區, sPID陣列並導致未定義的行為。

當然,實際的結果是未定義的,但是典型的C ++實現最終會破壞堆棧中下一個變量的第一個字節,即:

int iFIFO;

這是你的文件描述符。 所以,如果你的運氣耗盡並且你的新進程獲得了一個五位數的進程ID,這是一個小端C ++實現,沒有填充,那么iFIFO的低位字節被設置為0,如果代碼在沒有任何優化的情況下編譯, iFIFO文件描述符被設置為0.接着是Hillarity。

此外,在管道的另一側:

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'來終止讀取輸入(當然,確保讀取緩沖區足夠大atoi()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM