2013-01-16 61 views
9

我想有一個Perl守護接受來自客戶端的傳入連接,然後 & EXEC另一個Perl程序繼續進行與客戶的對話。Perl的 - 通過一個開放的插座通過fork/EXEC

我可以做到這一點很好,當只是分叉 - 守護程序代碼也包含孩子的代碼。但我沒有看到開放套接字如何通過exec()傳遞給另一個Perl程序。

不知何故,我覺得這在Unix(這是我的環境)中很容易,因此也是在Perl中。它可以做到嗎?

回答

14

這可以完成大約三個步驟:

  1. 清除近距離上的exec文件描述符標誌。
  2. 告訴exec'd程序使用哪個文件描述符。
  3. 將文件描述符還原爲句柄。

1. Perl(默認情況下)在打開的文件描述符上設置close-on-exec標誌。這意味着文件描述符將不會保留在exec之間。你必須先清除此標誌:

use Fcntl; 

my $flags = fcntl $fh, F_GETFD, 0 or die "fcntl F_GETFD: $!"; 
fcntl $fh, F_SETFD, $flags & ~FD_CLOEXEC or die "fcntl F_SETFD: $!"; 

2.現在,文件描述符將跨越exec保持打開,你需要告訴程序,描述它:

my $fd = fileno $fh; 
exec 'that_program', $fd; # pass it on the command line 
# (you could also pass it via %ENV or whatever) 

3 。恢復對對方的文件句柄:

my $fd = $ARGV[0]; # or however you passed it 
open my $fh, '+<&=', $fd; # fdopen 
$fh->autoflush(1); # because "normal" sockets have that enabled by default 

現在你有一個每再次在$fh的l級句柄。

附錄:作爲池上在評論中提到,你也可以確保插座使用三個「標準」文件中描述的一個(0(標準輸入),1(標準輸出),2(錯誤))其中1.默認情況下跨exec執行,2.有已知數字,因此不需要傳遞任何東西,3. 3. perl會自動爲它們創建相應的句柄。

open STDIN, '+<&', $fh; # now STDIN refers to the socket 
exec 'that_program'; 

現在that_program可以簡單地使用STDIN。這甚至可以用於輸出。對文件描述符0,1,2沒有固有的限制,它們僅用於輸入或輸出。這只是所有unix程序遵循的慣例。

+0

我即將試用您的程序,但我有一個關於使用STDIN的問題:它是否可以綁定到雙向連接,如套接字?我傾向於認爲fds 0-2是半魔法的(專門用於終端I/O)。除了你在附錄中提到的方式之外,它們是否真的很特別? – Chap

+0

我的解決方案存在的問題是打開輸入和輸出的FD。 '打開我的$ fh,'<&=',$ fd;'只是打開它的輸入。我試着用'open $ fh',>&=',$ fd;'來試試這個,但是卻得到錯誤:錯誤的文件描述符。 (前面爲輸入工作打開。)我找不到有關如何打開輸入和輸出的任何信息。 – Chap

+1

另一個後續:open(對於雙向I/O)應該是'open $ fh'+>&=',$ fd;'。另外,我需要發出'$ fh-> autoflush(1)'。 – Chap