2012-02-14 27 views
4

我在Linux上有一個很大的C++應用程序,有許多第一方和第三方庫被構建和鏈接。如何以編程方式在大型Linux應用程序中「拔出網線」?

該應用程序的某些部分應該在不訪問文件系統或網絡的情況下執行(特別是加載聯網文件)。我們定期發現這個操作確實通常是由於程序員錯誤而加載文件。

如何在代碼中執行此操作?例如,如下所示:

try { 
    lockFileSystem(); 
    Application->DoImportantOperation(); 
    unlockFileSystem(); 
} catch (InvalidFileSystemAccess) 
{ 
// bad programmer, no pizza 
} 

或者還有某種低級別的回調,應用程序可以在文件打開時掛鉤?

注意我知道strace的可怕性,但它已經到了需要作爲應用程序執行的一部分執行的地步,而不是作爲事後手動測試。

+0

*它是如何加載文件?你能不能'#including '? – Beta 2012-02-14 23:46:13

+0

加載在編譯時不可執行。應用程序本質上運行一個腳本,並且一些部分不應該訪問文件系統。 – Justicle 2012-02-14 23:48:46

+1

在chroot中啓動應用程序?設置一些iptables規則來拒絕應用程序訪問您的文件服務器?設置一個SELinux策略?不允許應用程序運行的用戶訪問裝載點?在自己的網絡名稱空間/ VRF域中運行應用程序? ... – ninjalj 2012-02-15 00:01:33

回答

5

這取決於代碼合法地嘗試做什麼,但您可以使用setrlimit()RLIMIT_NOFILE做到這一點。

像這樣的東西應該工作:

#include <sys/resource.h> 

struct scoped_fd_blocker { 
    rlim_t prev; 
    scoped_fd_blocker() { 
     rlimit lim; 
     getrlimit(RLIMIT_NOFILE, &lim); // get the current limit 
     prev = lim.rlim_cur; // save old limit 
     lim.rlim_cur = 0; // set the soft limit to 0 
     setrlimit(RLIMIT_NOFILE, &lim); // do the set 
    } 

    ~scoped_fd_blocker() { 
     rlimit lim; 
     getrlimit(RLIMIT_NOFILE, &lim); // get the current limit 
     lim.rlim_cur = prev; // reset the soft limit to the previous value 
     setrlimit(RLIMIT_NOFILE, &lim); // do the set 
    } 
}; 


// Example Usage: 
void do_stuff() { 
    scoped_fd_blocker blocker; 
    Application->DoImportantOperation(); 
} 

基本上這告訴OS不要讓你的程序打開任何文件描述符,即使現有的閉合,通過清空軟開文件描述符限制的過程。請注意,這不僅僅是文件,還可能會產生一些意想不到的後果。這將包括文件,套接字,事件對象,目錄,共享資源,管道,並且還會阻止C庫打開文件。 (有些C庫確實使用文件鎖和內容來管理併發性。)想想所有打開文件的東西(例如dlopen)。

任何嘗試打開文件描述符都將失敗(返回-1),而errno將被設置爲EMFILE,這將轉換爲「錯誤24:打開的文件過多」。

我把整個事情放在一個結構體中,以便它非常強大的異常安全。

+0

這看起來很有前途。讀這個,http://linux.die.net/man/2/setrlimit我不知道調用'setr​​limit'是否需要超級用戶權限。我想象不到,因爲它在同一個過程中被調用。 – Justicle 2012-02-15 01:16:27

+1

爲RAII包裝+1! – 2012-02-15 07:11:59

+0

@Jittericle提高rlim_max高於getrlimit返回的值將需要root權限。與rlim_cur混淆不會(但它不能超過rlim_max)。這也意味着如果你降低rlim_max你不能再提高它。 – SoapBox 2012-02-15 09:40:55

2

不是很優雅,但你可以掛鉤例如open()並通過你自己的具有狀態的proxy_open()類型的調用進行路由。如果狀態是「不允許文件系統!」那麼你只需返回適當的錯誤和/或處理它,但不管你喜歡。

相關問題