2010-06-16 104 views
1

我正在研究用於Linux的C++ initramfs的init。該腳本用於解鎖帶有加密驅動器的DM-Crypt,並將LVM驅動器設置爲可用。在Linux系統()調用的問題

由於我不想重新實現cryptsetupgpg的功能,我正在使用系統調用來調用可執行文件。使用系統調用來調用gpg可以正常工作,如果我已經完全啓動了系統(我已經有了一個基於initramfs的bash腳本,在啓動時可以正常工作,並且我使用grub編輯命令行以使用舊的initramfs)。但是,在initramfs中它甚至不會像調用它一樣。即使命令如system("echo BLAH");失敗。

那麼,有沒有人有任何投入?


編輯:所以我想出了什麼導致了我的錯誤。我沒有線索爲什麼它會導致錯誤,但我發現它。

爲了讓熱插拔,我需要寫/sbin/mdev/proc/sys/kernel/hotplug ......不過,我結束了周圍的參數開關(上的功能我寫我自己不會少),所以我在寫/proc/sys/kernel/hotplug/sbin/mdev

我不知道爲什麼會導致問題,但它確實如此。

回答

6

Amardeep日誌是正確的,system()對POSIX類型系統通過/bin/sh運行命令。

我懷疑你實際上是否有合理的需要調用你通過Bourne shell提到的這些程序。一個很好的理由是,如果你需要他們擁有一組默認的環境變量,但由於/etc/profile在引導過程中很可能還沒有提供,所以我沒有看到這種情況。

相反,使用標準fork()/exec()模式:

int system_alternative(const char* pgm, char *const argv[]) 
{ 
    pid_t pid = fork(); 
    if (pid > 0) { 
     // We're the parent, so wait for child to finish 
     int status; 
     waitpid(pid, &status, 0); 
     return status; 
    } 
    else if (pid == 0) { 
     // We're the child, so run the specified program. Our exit status will 
     // be that of the child program unless the execv() syscall fails. 
     return execv(pgm, argv); 
    } 
    else { 
     // Something horrible happened, like system out of memory 
     return -1; 
    } 
} 

如果你需要從這個過程被稱爲標準輸出讀取或發送數據到其標準輸入,則需要通過pipe()dup2()做一些標準手柄重定向在那裏。

你可以在任何一本優秀的Unix編程書籍中瞭解這方面的知識。我推薦使用W. Richard Stevens在UNIX環境中的高級編程。由Rago合着的第二版增加了一些材料,以涵蓋史蒂文斯編寫第一版(如Linux和OS X)以來出現的平臺,但自從原始版本以來,這樣的基礎知識沒有改變。

+0

非常感謝您的幫助。您實際上回答了一個問題,我沒有問過爲什麼它在manpages中說的地獄使用'exec()'系列函數而不是'system()'時,他們有非常不同的效果。如果你不介意,你有一個有用的管道輸出鏈接? (無論哪種方式,我確實訂購了你建議的書,所以我最終會得到一個很好的資源:)) – Thomas 2010-06-18 01:50:10

+1

史蒂文斯在第一版的第14.2節中介紹了它。在第二版中,它轉到了第15.2節。 – 2010-06-18 05:20:48

+0

謝謝。我一定會去找的。 – Thomas 2010-06-19 02:40:32

6

我相信system()函數在shell中執行你的命令。在啓動過程的早期,shell可執行文件是否已安裝並可用?您可能想使用fork()和execve()進行研究。

編輯:請確保您的加密工具也在安裝捲上。

1

你在initramfs中有什麼?你可以做到以下幾點:

int main() { 
    return system("echo hello world"); 

} 

然後在這樣的一個啓動腳本與strace它:

strace -o myprog.log myprog 

看一次你的系統啓動