如何查找linux内核中定义的枚举

如何查找linux内核中定义的枚举,第1张

1.安装ctags

在源代码目录下运行

ctags -R

这样,会递归生成当前目录下及其子目录的tags文件。

2.使用VIM根据tags文件查找函数或结构定义。

1.在源码目录下查找

vi -t tagname

2.如果要在任意位置使用,则需要把该tags文件添加到~/.vimrc文件中

set tags=/home/money/sda8/2.6232/tags

3.如果要在代码中实时跟踪,则光标移动到函数名上,使用CTRL+]键,按CTRL+t可以返回。

如果要跟踪系统函数,使用shift+K可以自动跳转道光标所在函数的手册。

在Linux下,lspci可以枚举所有PCI设备。它是通过读取PCI配置空间(PCI Configuration Space)信息来实现PCI设备的枚举的。这里,我通过两种方式来简单的模拟一下lspci的功能。一种是通过PCI总线的CF8和CFC端口来枚举(参考PCI总线规范);另一种是利用proc filesystem。

方法一:这种方法需要对端口进行 *** 作,在Linux下,普通应用程序没有权限读写I/O 端口,需要通过iopl或ioperm来提升权限,我的代码里面使用iopl。

[cpp] view plaincopyprint?

/*

* Enum all pci device via the PCI config register(CF8 and CFC).

*/

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/io.h>

#define PCI_MAX_BUS 255 /* 8 bits (0 ~ 255) */

#define PCI_MAX_DEV 31 /* 5 bits (0 ~ 31) */

#define PCI_MAX_FUN 7 /* 3 bits (0 ~ 7) */

#define CONFIG_ADDRESS 0xCF8

#define CONFIG_DATA 0xCFC

#define PCICFG_REG_VID 0x00 /* Vendor id, 2 bytes */

#define PCICFG_REG_DID 0x02 /* Device id, 2 bytes */

#define PCICFG_REG_CMD 0x04 /* Command register, 2 bytes */

#define PCICFG_REG_STAT 0x06 /* Status register, 2 bytes */

#define PCICFG_REG_RID 0x08 /* Revision id, 1 byte */

void list_pci_devices()

{

unsigned int bus, dev, fun

unsigned int addr, data

//printf("BB:DD:FF VID:DID\n")

for (bus = 0bus <= PCI_MAX_BUSbus++) {

for (dev = 0dev <= PCI_MAX_DEVdev++) {

for (fun = 0fun <= PCI_MAX_FUNfun++) {

addr = 0x80000000L | (bus<<16) | (dev<<11) | (fun<<8)

outl(addr, CONFIG_ADDRESS)

data = inl(CONFIG_DATA)

/* Identify vendor ID */

if ((data != 0xFFFFFFFF) &&(data != 0)) {

printf("%02X:%02X:%02X ", bus, dev, fun)

printf("%04X:%04X", data&0xFFFF, data>>16)

addr = 0x80000000L | (bus<<16) | (dev<<11) | (fun<<8) | PCICFG_REG_RID

outl(addr, CONFIG_ADDRESS)

data = inl(CONFIG_DATA)

if (data&0xFF) {

printf(" (rev %02X)\n", data&0xFF)

} else {

printf("\n")

}

}

} end func

} // end device

} // end bus

}

int main()

{

int ret

/* Enable r/w permission of all 65536 ports */

ret = iopl(3)

if (ret <0) {

perror("iopl set error")

return 1

}

list_pci_devices()

/* Disable r/w permission of all 65536 ports */

ret = iopl(0)

if (ret <0) {

perror("iopl set error")

return 1

}

return 0

}

方法二:这种方法需不需要对端口进行 *** 作,而是利用Linux procfs来实现对PCI 配置空间的访问。

[cpp] view plaincopyprint?

/*

* Enum all pci device via /proc/bus/pci/.

*/

#include <stdio.h>

#include <stdint.h>

#include <stdlib.h>

#include <string.h>

#include <fcntl.h>

#include <unistd.h>

#define PCI_MAX_BUS 255 /* 8 bits (0 ~ 255) */

#define PCI_MAX_DEV 31 /* 5 bits (0 ~ 31) */

#define PCI_MAX_FUN 7 /* 3 bits (0 ~ 7) */

/*

* PCI Configuration Header offsets

*/

#define PCICFG_REG_VID 0x00 /* Vendor id, 2 bytes */

#define PCICFG_REG_DID 0x02 /* Device id, 2 bytes */

#define PCICFG_REG_CMD 0x04 /* Command register, 2 bytes */

#define PCICFG_REG_STAT 0x06 /* Status register, 2 bytes */

#define PCICFG_REG_RID 0x08 /* Revision id, 1 byte */

#define PCICFG_REG_PROG_INTF 0x09 /* Programming interface code, 1 byte */

#define PCICFG_REG_SUBCLASS 0x0A /* Sub-class code, 1 byte */

#define PCICFG_REG_BASCLASS 0x0B /* Base class code, 1 byte */

#define PCICFG_REG_CACHE_LINESZ 0x0C /* Cache line size, 1 byte */

#define PCICFG_REG_LATENCY_TIMER 0x0D /* Latency timer, 1 byte */

#define PCICFG_REG_HEADER_TYPE 0x0E /* Header type, 1 byte */

#define PCICFG_REG_BIST 0x0F /* Builtin self test, 1 byte */

#define PCICFG_REG_BAR0 0x10 /* Base addr register 0, 4 bytes */

#define PCICFG_REG_BAR1 0x14 /* Base addr register 1, 4 bytes */

#define PCICFG_REG_BAR2 0x18 /* Base addr register 2, 4 bytes */

#define PCICFG_REG_BAR3 0x1C /* Base addr register 3, 4 bytes */

#define PCICFG_REG_BAR4 0x20 /* Base addr register 4, 4 bytes */

#define PCICFG_REG_BAR5 0x24 /* Base addr register 5, 4 bytes */

#define PCICFG_REG_CIS 0x28 /* Cardbus CIS Pointer */

#define PCICFG_REG_SVID 0x2C /* Subsystem Vendor ID, 2 bytes */

#define PCICFG_REG_SDID 0x2E /* Subsystem ID, 2 bytes */

#define PCICFG_REG_ROMBAR 0x30 /* ROM base register, 4 bytes */

#define PCICFG_REG_CAPPTR 0x34 /* Capabilities pointer, 1 byte */

#define PCICFG_REG_INT_LINE 0x3C /* Interrupt line, 1 byte */

#define PCICFG_REG_INT_PIN 0x3D /* Interrupt pin, 1 byte */

#define PCICFG_REG_MIN_GNT 0x3E /* Minimum grant, 1 byte */

#define PCICFG_REG_MAX_LAT 0x3F /* Maximum lat, 1 byte */

void list_pci_devices()

{

unsigned int bus, dev, fun

//printf("BB:DD:FF VID:DID(RID)\n")

for (bus = 0bus <= PCI_MAX_BUSbus++) {

for (dev = 0dev <= PCI_MAX_DEVdev++) {

for (fun = 0fun <= PCI_MAX_FUNfun++) {

char proc_name[64]

int cfg_handle

uint32_t data

uint16_t vid, did

uint8_t rid

snprintf(proc_name, sizeof(proc_name),

"/proc/bus/pci/%02x/%02x.%x", bus, dev, fun)

cfg_handle = open(proc_name, O_RDWR)

if (cfg_handle <= 0)

continue

lseek(cfg_handle, PCICFG_REG_VID, SEEK_SET)

read(cfg_handle, &data, sizeof(data))

/* Identify vendor ID */

if ((data != 0xFFFFFFFF) &&(data != 0)) {

lseek(cfg_handle, PCICFG_REG_RID, SEEK_SET)

read(cfg_handle, &rid, sizeof(rid))

vid = data&0xFFFF

did = data>>16

printf("%02X:%02X:%02X", bus, dev, fun)

if (rid >0) {

printf(" %04X:%04X (rev %02X)\n", vid, did, rid)

} else {

printf(" %04X:%04X\n", vid, did)

}

}

} // end func

} // end device

} // end bus

}

int main(int argc, char **argv)

{

list_pci_devices()

return 0

}

这两种方法各有优缺点,第一种方法方便移植到其他OS,第二种就只适用于Linux。但是,第一种方法需要对I/O port进行直接 *** 作。第二种就不需要。

注意:执行这两段代码时,需要超级用户(root) 权限。

补充:今天在枚举 Westmere-EP Processor(Intel Xeon Processor 5500 Series(Nehalem-EP))的 IMC(Integrated Memory Controller)时发现一个问题。lspci无法枚举到IMC设备。Westmere-EP 是 Intel 新的处理器架构。和以往的CPU不一样,它把Memory Controller集成到了CPU里面。IMC控制器被映射到了PCI总线上,Bus Number 是0xFE~0xFF,procfs(/proc/bus/pci/)下没有这几个设备。但是,通过 CF8/CFC 端口可以枚举到这些设备。

3. 这段代码是在驱动中可以用来查找特定的pci device,并且返回一个pci_dev的结构体变量。通过这样一个struct变量,内核提供的接口函数可以直接套用,如pci_read_config_word(),pci_write_config_word()等。

[cpp] view plaincopyprint?

void list_pci_device()

{

struct pci_dev *dev

struct pci_bus *bus,*childbus

list_for_each_entry(bus, &pci_root_buses, node) { //globle pci_root_buses in pci.h

list_for_each_entry(dev, &bus->devices, bus_list) { // for bus 0

printk("%02X:%02X:%02X %04X:%04X\n",dev->bus->number,dev->devfn >>3, dev->devfn &0x07,dev->vendor,dev->device)

}

list_for_each_entry(childbus, &bus->children,node) { // for bus 1,2,3,...

list_for_each_entry(dev, &childbus->devices, bus_list) {

printk("%02X:%02X:%02X %04X:%04X\n",dev->bus->number,dev->devfn >>3, dev->devfn &0x07,dev->vendor,dev->device)

}

}

}

1、创建定时任务 命令行打开终端

crontab -e

登录后复制

2、输入启动脚本 以下命令为:系统重启后90秒 启动redis服务

@reboot ( sleep 90 sh /usr/local/bin/redis-server )

登录后复制

三、使用chkonfig

单独查看某一服务是否开机启动的命令 :chkconfig --list 服务名

单独开启某一服务的命令 chkconfig 服务名 on

单独关闭某一服务的命令;chkconfig 服务名 off

查看某一服务的状态:/etc/intd.d/服务名 status

设置完成之后,重启一下即可


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/8517731.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-17
下一篇 2023-04-17

发表评论

登录后才能评论

评论列表(0条)

保存