如性能报告分析所示,我的用户应用程序在从 PCI 设备读取数据时与内核进行交互,特别是通过名为 pci_user_write_config_dword 的函数。
我有兴趣探索这个函数以理解它为什么调用 _raw_spin_lock_irq。
我一直无法找到这个功能的实际实现。 我只在以下位置的内核源代码中找到了它的定义:https://elixir.bootlin.com/linux/v5.18.19/source/include/linux/pci.h#L1235
Linux内核源代码中哪里可以找到pci_user_write_config_dword的实现?
user_ application [kernel.kallsyms] [k] do_syscall_64
|
|--90.82%--do_syscall_64
| |
| |--61.22%--__x64_sys_pwrite64
| | |
| | --61.21%--ksys_pwrite64
| | |
| | --61.05%--vfs_write
| | |
| | --60.87%--__vfs_write
| | |
| | --60.79%--kernfs_fop_write
| | |
| | --60.19%--sysfs_kf_bin_write
| | |
| | --60.18%--pci_write_config
| | |
| | |--57.62%--pci_user_write_config_dword
| | | |
| | | |--35.92%--_raw_spin_lock_irq
| | | | |
| | | | --35.88%--native_queued_spin_lock_slowpath
您可以在 drivers/pci/access.c 中找到它:
/* Returns 0 on success, negative values indicate error. */
#define PCI_USER_WRITE_CONFIG(size, type) \
int pci_user_write_config_##size \
(struct pci_dev *dev, int pos, type val) \
{ \
int ret = PCIBIOS_SUCCESSFUL; \
if (PCI_##size##_BAD) \
return -EINVAL; \
raw_spin_lock_irq(&pci_lock); \
if (unlikely(dev->block_cfg_access)) \
pci_wait_cfg(dev); \
ret = dev->bus->ops->write(dev->bus, dev->devfn, \
pos, sizeof(type), val); \
raw_spin_unlock_irq(&pci_lock); \
return pcibios_err_to_errno(ret); \
} \
EXPORT_SYMBOL_GPL(pci_user_write_config_##size);
您可能会发现它比平时更难搜索,因为一整类函数(对字节、字、双字进行操作)是通过使用 C 预处理器的标记串联功能加上方便的辅助宏一次性定义的。这在代码方面是经济的,但可能会击败 cscope 等代码浏览器。如果您不熟悉,您可以在here阅读有关 C 令牌串联的内容,并开始使用它使您自己的内核代码更加紧凑。