簡體   English   中英

Linux設備驅動程序中的靜態函數

[英]Static functions in Linux device driver

為什么大多數設備驅動程序中的每個功能都是靜態的? 由於靜態函數在文件范圍之外不可見。 那么,這些驅動程序函數如何被用戶空間應用程序調用?

記住比在C中一切都是地址。 這意味着如果你有地址,你可以調用一個函數。 內核有一個名為EXPORT_SYMBOL的宏,它就是這樣做的。 它導出函數的地址,以便可以調用驅動程序函數而無需放置標頭聲明,因為這些函數有時在編譯時不知道。 在這種情況下,靜態限定符只是為了確保它們只通過這種方法調用,而不是從可能包含該驅動程序代碼的其他文件中調用(在某些情況下,包含驅動程序代碼頭並直接調用它們不是一個好主意) 。

編輯:因為有人指出我沒有覆蓋用戶空間。

驅動程序函數通常不是直接通過用戶空間調用的(除了SYSCALL指令的x86實現,它有時會做一些小技巧來保存上下文切換)。 所以這里的靜態關鍵字沒有區別。 它只會對內核空間產生影響。 正如@Cong Wang所指出的,函數通常放在函數指針的結構中,這樣它們就可以通過簡單地讓結構指向這個結構來調用它們(比如file_ops,調度程序,文件系統,網絡代碼等......)。

因為這些靜態函數不應該直接在模塊外部使用。 它們由模塊中的其他函數調用,其中可以是ioctl的接口或任何回調。 這就是為什么可以從用戶空間調用它們,它們只是在調用路徑中。

看看網絡虛擬模塊:

dummy_dev_init()顯然是靜態的:

static int dummy_dev_init(struct net_device *dev)
{
        dev->dstats = alloc_percpu(struct pcpu_dstats);
        if (!dev->dstats)
                return -ENOMEM;

        return 0;
}

但它是 - > ndo_init()的回調,在注冊此網絡設備時調用它。

static const struct net_device_ops dummy_netdev_ops = {
        .ndo_init               = dummy_dev_init,
        .ndo_uninit             = dummy_dev_uninit,
        .ndo_start_xmit         = dummy_xmit,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_rx_mode        = set_multicast_list,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_get_stats64        = dummy_get_stats64,
        .ndo_change_carrier     = dummy_change_carrier,
};

顯而易見,沒有人應該直接調用dummy_dev_init()。

內核有數千個模塊,它們是(或曾經是)所有目標文件,通過類似於鏈接的過程動態加載 - 或者實際上是鏈接到可執行文件中。 你能想象如果它們都要導出所有的函數名會有多少名稱沖突,除非指定static否則默認的C行為是什么?

用戶空間應用程序不能直接調用驅動程序函數,但還有其他交互方式

暫無
暫無

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

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