​Linux下C如何调用PCI Lib函数

简介:

Linux下C如何调用PCI Lib函数

在Linux下,可以通过"setpci"和"setpci"命令来访问PCI设备的配置空间,那么能否用程序来访问PCI 配置空间呢?答案当然是肯定的,linux下提供了多个pci库以供应用程序访问。下面就以最常见的为例,从安装、使用和编译的角度分别进行说明。


安装
在centos中,用超级用户权限,可用下面的命令查看到和pci访问相关的库包括:
libpciaccess.i686 : PCI access library
libpciaccess.x86_64 : PCI access library
libpciaccess-devel.i686 : PCI access library development package
libpciaccess-devel.x86_64 : PCI access library development package
pciutils.x86_64 : PCI bus related utilities
pciutils-devel.i686 : Linux PCI development library
pciutils-devel.x86_64 : Linux PCI development library
pciutils-devel-static.i686 : Linux PCI static library
pciutils-devel-static.x86_64 : Linux PCI static library
pciutils-libs.i686 : Linux PCI library
pciutils-libs.x86_64 : Linux PCI library

由于实际系统是64bit的,并且以静态库的形式进行使用,可以用下面的命令安装pci lib 库: 
 yum install libpciaccess.x86_64 libpciaccess-devel.x86_64 pciutils-devel-static.x86_64
安装完后,可以看到相应的头文件已经最/usr/include下面了:
[root@localhost include]# find ./ -name "*pci*"
./linux/pci.h
./linux/pci_regs.h
./linux/virtio_pci.h
./sys/pci.h
./pci
./pci/pci.h
./pciaccess.h
并且静态库也已经存在了:
[root@localhost lib64]# find ./ -name "*pci*"
./kde4/kcm_pci.so
./pkgconfig/libpci.pc
./pkgconfig/pciaccess.pc
./libpci.so.3
./libpci.so.3.2.1
./libpciaccess.so.0
./libpciaccess.so.0.11.1
./libpci.so
./libpci.a
./libpciaccess.so
通过上面的输出可以看到,libpciaccess只有动态库的形式,而libpci既有动态库也有静态库,这个和我们输入的" yum install libpciaccess.x86_64 libpciaccess-devel.x86_64 pciutils-devel-static.x86_64"命令是吻合的。


使用

打开/usr/include/pci/pci.h,可以找到我们需要的函数:
u8 pci_read_byte(struct pci_dev *, int pos) PCI_ABI; /* Access to configuration space */
u16 pci_read_word(struct pci_dev *, int pos) PCI_ABI;
u32 pci_read_long(struct pci_dev *, int pos) PCI_ABI;
int pci_read_block(struct pci_dev *, int pos, u8 *buf, int len) PCI_ABI;
int pci_read_vpd(struct pci_dev *d, int pos, u8 *buf, int len) PCI_ABI;
int pci_write_byte(struct pci_dev *, int pos, u8 data) PCI_ABI;
int pci_write_word(struct pci_dev *, int pos, u16 data) PCI_ABI;
int pci_write_long(struct pci_dev *, int pos, u32 data) PCI_ABI;
int pci_write_block(struct pci_dev *, int pos, u8 *buf, int len) PCI_ABI;

打开/usr/include/pciaccess.h,也有可以访问配置空间的函数:
struct pci_io_handle *pci_device_open_io(struct pci_device *dev, pciaddr_t base,
                     pciaddr_t size);
struct pci_io_handle *pci_legacy_open_io(struct pci_device *dev, pciaddr_t base,
                     pciaddr_t size);
void pci_device_close_io(struct pci_device *dev, struct pci_io_handle *handle);
uint32_t pci_io_read32(struct pci_io_handle *handle, uint32_t reg);
uint16_t pci_io_read16(struct pci_io_handle *handle, uint32_t reg);
uint8_t pci_io_read8(struct pci_io_handle *handle, uint32_t reg);
void pci_io_write32(struct pci_io_handle *handle, uint32_t reg, uint32_t data);
void pci_io_write16(struct pci_io_handle *handle, uint32_t reg, uint16_t data);
void pci_io_write8(struct pci_io_handle *handle, uint32_t reg, uint8_t data);
从上面的两组函数接口来看,可以看到pciutils需要初始化struct pci_dev,而pciasscess库需要初始化struct pci_io_handle *handle。那么该如何使用pciutils静态库呢,通过继续阅读/usr/include/pci/pci.h,可以看到下面的函数声明和注释:
/* Initialize PCI access */
struct pci_access *pci_alloc(void) PCI_ABI;
void pci_init(struct pci_access *) PCI_ABI;
void pci_cleanup(struct pci_access *) PCI_ABI;

/* Scanning of devices */
void pci_scan_bus(struct pci_access *acc) PCI_ABI;
struct pci_dev *pci_get_dev(struct pci_access *acc, int domain, int bus, int dev, int func) PCI_ABI; /* Raw access to specified device */
void pci_free_dev(struct pci_dev *) PCI_ABI;
据此我们不难猜测出使用pciutils的代码流程,并且根据头文件说明实现一个测试代码test_pcilib.c:
int main(void)
{
        int i = 0;
        int ret = 0;

        struct pci_access * myaccess;
        struct pci_dev * mydev;

        myaccess = pci_alloc();
        pci_init(myaccess);

        mydev = pci_get_dev(myaccess, 0, 6, 0, 0);

        for (i = 0; i < 256; i++) {
                ret = pci_read_byte(mydev, i);
                printf("%d: %02x\n", i, ret);
        }

        pci_free_dev(mydev);

        pci_cleanup(myaccess);

        return 0;
}


编译


因为已经知道上面的代码依赖于libpci.a静态库,为此可用用下面的gcc命令进行简单编译:
[root@localhost testcases]# gcc -c -o test_pci.o test_pcilib.c
[root@localhost testcases]# gcc -Wall -o test_pci test_pci.o /usr/lib64/libpci.a
[root@localhost testcases]# ./test_pci
0: b5
1: 10
2: a0
3: 87
4: 07
5: 04
6: 10
7: 00
8: ca
9: 00
10: 80
11: 06
12: 10
.....


















本文转自存储之厨51CTO博客,原文链接:http://blog.51cto.com/xiamachao/1744433 ,如需转载请自行联系原作者



相关文章
|
存储 Linux
linux中的目录操作函数
本文详细介绍了Linux系统编程中常用的目录操作函数,包括创建目录、删除目录、读取目录内容、遍历目录树以及获取和修改目录属性。这些函数是进行文件系统操作的基础,通过示例代码展示了其具体用法。希望本文能帮助您更好地理解和应用这些目录操作函数,提高系统编程的效率和能力。
503 26
|
Linux
【Linux】System V信号量详解以及semget()、semctl()和semop()函数讲解
System V信号量的概念及其在Linux中的使用,包括 `semget()`、`semctl()`和 `semop()`函数的具体使用方法。通过实际代码示例,演示了如何创建、初始化和使用信号量进行进程间同步。掌握这些知识,可以有效解决多进程编程中的同步问题,提高程序的可靠性和稳定性。
1113 19
|
Linux Android开发 开发者
linux m、mm、mmm函数和make的区别
通过理解和合理使用这些命令,可以更高效地进行项目构建和管理,特别是在复杂的 Android 开发环境中。
1062 18
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
782 13
|
Linux Shell
Linux系统编程:掌握popen函数的使用
记得在使用完 `popen`打开的流后,总是使用 `pclose`来正确关闭它,并回收资源。这种做法符合良好的编程习惯,有助于保持程序的健壮性和稳定性。
1100 6
|
Linux Shell
Linux系统编程:掌握popen函数的使用
记得在使用完 `popen`打开的流后,总是使用 `pclose`来正确关闭它,并回收资源。这种做法符合良好的编程习惯,有助于保持程序的健壮性和稳定性。
630 3
在Linux内核中根据函数指针输出函数名称
在Linux内核中根据函数指针输出函数名称
|
Linux PHP
Linux CentOS 宝塔 Suhosin禁用php5.6版本eval函数详细图文教程
【8月更文挑战第27天】本文介绍两种禁用PHP执行的方法:使用`PHP_diseval_extension`禁用和通过`suhosin`禁用。由于`suhosin`不支持PHP8,仅适用于PHP7及以下版本,若服务器安装了PHP5.6,则需对应安装`suhosin-0.9.38`版本。文章提供了详细的安装步骤,并强调了宝塔环境下与普通环境下的PHP路径差异。安装完成后,在`php.ini`中添加`suhosin.so`扩展并设置`executor.disable_eval = on`以禁用执行功能。最后通过测试代码验证是否成功禁用,并重启`php-fpm`服务生效。
570 2
|
Shell Linux C语言
Linux0.11 execve函数(六)
Linux0.11 execve函数(六)
871 1
|
Linux API
Linux源码阅读笔记07-进程管理4大常用API函数
Linux源码阅读笔记07-进程管理4大常用API函数