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