这个是一些列分析,主要用于帮助自己的理解和记录思考时候的一些笔记。 device_list.c // 库文件的导入#include config.h#include stdio.h#include endian.h#include infiniband/verbs.hint main(int argc, char *arg
这个是一些列分析,主要用于帮助自己的理解和记录思考时候的一些笔记。
device_list.c
// 库文件的导入
#include <config.h>
#include <stdio.h>
#include <endian.h>
#include <infiniband/verbs.h>
int main(int argc, char *argv[])
{
struct ibv_device **dev_list; // 等价于struct ibv_device dev_list[][],类似一个二维数组,数组里面每一个都是存储ibv_device信息的
int num_devices, i;
dev_list = ibv_get_device_list(&num_devices); // 这个就是获取这个机器上面能够获取到的所有的RDMA设备信息,然后把信息存储在dev_list里面。
if (!dev_list) {
perror("Failed to get IB devices list");
return 1;
}
// 打印相关的设备的厂商信息GUID和设备信息
printf(" %-16s\t node GUID\n", "device");
printf(" %-16s\t----------------\n", "------");
// 具体的打印过程
for (i = 0; i < num_devices; ++i) {
printf(" %-16s\t%016llx\n",
ibv_get_device_name(dev_list[i]),
(unsigned long long) be64toh(ibv_get_device_guid(dev_list[i])));
}
ibv_free_device_list(dev_list); // 释放dev_list里面的所有设备信息,避免内存泄漏。
return 0;
}
总结:获取设备信息,并且打印所有的设备信息和GUID,最后把获取的设备资源释放掉,避免内存泄漏。
asyncwatch.c
// 主函数,阅读入口
int main(int argc, char *argv[])
{
struct ibv_device **dev_list; // 设备数组
struct ibv_context *context; // ibv的上下文(个人理解就是具体操作的设备上下文信息)
struct ibv_async_event event; // 异步事件
char *ib_devname = NULL; // 具体使用的设备名称
int i = 0;
/* Force line-buffering in case stdout is redirected */
setvbuf(stdout, NULL, _IOLBF, 0); // stdout是标准的输出流指针,输出到屏幕。整个功能是,在屏幕上面只要遇到\n就覆情况,然后刷新屏幕信息。
while (1) {
int ret = 1;
int c;
static struct option long_options[] = {
{ .name = "ib-dev", .has_arg = 1, .val = 'd' },
{ .name = "help", .has_arg = 0, .val = 'h' },
{}
};
c = getopt_long(argc, argv, "d:h", long_options, NULL); // 参数解析,只接受d和h的参数
if (c == -1)
break;
switch (c) {
case 'd':
ib_devname = strdupa(optarg);
break;
case 'h':
ret = 0;
SWITCH_FALLTHROUGH;
default:
usage(argv[0]);
return ret;
}
}
dev_list = ibv_get_device_list(NULL); // 用于获取所有的dev信息存储在dev_list里面。
if (!dev_list) {
perror("Failed to get IB devices list");
return 1;
}
// 指定了设备名称,查找这个设备信息
if (ib_devname) {
for (; dev_list[i]; ++i) {
if (!strcmp(ibv_get_device_name(dev_list[i]), ib_devname))
break;
}
}
if (!dev_list[i]) {
fprintf(stderr, "IB device %s not found\n",
ib_devname ? ib_devname : "");
return 1;
}
context = ibv_open_device(dev_list[i]); // 把设备打开,保存设备的上下文(查资料看到,这个地方会顺便初始化context)
if (!context) {
fprintf(stderr, "Couldn't get context for %s\n",
ibv_get_device_name(dev_list[i]));
return 1;
}
// 打印设备名字和异步文件描述符信息
printf("%s: async event FD %d\n",
ibv_get_device_name(dev_list[i]), context->async_fd);
// 获取事件,然后打印信息
while (1) {
if (ibv_get_async_event(context, &event))
return 1;
printf(" event_type %s (%d), port %d\n",
event_name_str(event.event_type),
event.event_type, event.element.port_num);
ibv_ack_async_event(&event);
}
return 0;
}
上面最后几行代码里面有调用这个event_name_str函数,这个函数就是返回对应的事件信息。
static const char *event_name_str(enum ibv_event_type event_type)
{
switch (event_type) {
case IBV_EVENT_DEVICE_FATAL:
return "IBV_EVENT_DEVICE_FATAL";
case IBV_EVENT_PORT_ACTIVE:
return "IBV_EVENT_PORT_ACTIVE";
case IBV_EVENT_PORT_ERR:
return "IBV_EVENT_PORT_ERR";
case IBV_EVENT_LID_CHANGE:
return "IBV_EVENT_LID_CHANGE";
case IBV_EVENT_PKEY_CHANGE:
return "IBV_EVENT_PKEY_CHANGE";
case IBV_EVENT_SM_CHANGE:
return "IBV_EVENT_SM_CHANGE";
case IBV_EVENT_CLIENT_REREGISTER:
return "IBV_EVENT_CLIENT_REREGISTER";
case IBV_EVENT_GID_CHANGE:
return "IBV_EVENT_GID_CHANGE";
case IBV_EVENT_CQ_ERR:
case IBV_EVENT_QP_FATAL:
case IBV_EVENT_QP_REQ_ERR:
case IBV_EVENT_QP_ACCESS_ERR:
case IBV_EVENT_COMM_EST:
case IBV_EVENT_SQ_DRAINED:
case IBV_EVENT_PATH_MIG:
case IBV_EVENT_PATH_MIG_ERR:
case IBV_EVENT_SRQ_ERR:
case IBV_EVENT_SRQ_LIMIT_REACHED:
case IBV_EVENT_QP_LAST_WQE_REACHED:
default:
return "unexpected";
}
}
总结:首先解析命令行信息,然后获取设备和上下文信息,最后获取事件信息,然后打印事件的详细信息。
【文章原创作者:高防cdn http://www.558idc.com/gfcdn.html提供,感恩】