[英]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.