| 面向内核空间的 API
这些API接口向位于内核空间的用户提供了管理relay通道、数据写入等功能。下面介绍其中主要的部分,
完整的API接口列表请参见这里。
●relay_open() - 创建一个relay通道,包括创建每个CPU对应的relay缓冲区。
●relay_close() - 关闭一个relay通道,包括释放所有的relay缓冲区,在此之前会调用relay_switch()
来处理这些relay缓冲区以保证已读取但是未满的数据不会丢失
●relay_write() - 将数据写入到当前CPU对应的relay缓冲区内。由于它使用了local_irqsave()保护,
因此也可以在中断上下文中使用。
●relay_reserve() - 在relay通道中保留一块连续的区域来留给未来的写入操作。这通常用于那些希望
直接写入到relay缓冲区的用户。考虑到性能或者其它因素,这些用户不希望先把数据写到一个临时缓冲
区中,然后再通过relay_write()进行写入。
Relay的例子
我们用一个最简单的例子来介绍怎么使用Relay。这个例子由两部分组成:一部分是位于内核空间将数据
写入relay文件的程序,使用时需要作为一个内核模块被加载;另一部分是位于用户空间从relay文件中读
取数据的程序,使用时作为普通用户态程序运行。
内核空间的程序主要操作是:
加载模块时,打开一个relay通道,并且往打开的relay通道中写入消息;
卸载模块时,关闭relay通道。
程序内容:
/* * hello-mod.c * a kernel-space client example of relayfs filesystem */ #include #include static struct rchan *hello_rchan; int init_module(void) { const char *msg="Hello world\n"; hello_rchan = relay_open("cpu", NULL, 8192, 2, NULL); if(!hello_rchan){ printk("relay_open() failed.\n"); return -ENOMEM; } relay_write(hello_rchan, msg, strlen(msg)); return 0; } void cleanup_module(void) { if(hello_rchan) { relay_close(hello_rchan); hello_rchan = NULL; } return; } MODULE_LICENSE ("GPL"); MODULE_DESCRIPTION ("Simple example of Relay");
用户空间的函数主要操作是:
●如果relayfs文件系统还没有被mount,则将其mount到目录/mnt/relay上;
●遍历每一个CPU对应的缓冲文件;
●打开文件;
●读取所有文件内容;
●关闭文件;
●最后,umount掉relay文件系统。
程序内容:
/* * audience.c * a user-space client example of relayfs filesystem */ #include #include #include #include #include #include #include #define MAX_BUFLEN 256 const char filename_base[]="/mnt/relay/cpu"; // implement your own get_cputotal() before compilation static int get_cputotal(void); int main(void) { char filename[128]={0}; char buf[MAX_BUFLEN]; int fd, c, i, bytesread, cputotal = 0; if(mount("relayfs", "/mnt/relay", "relayfs", 0, NULL) && (errno != EBUSY)) { printf("mount() failed: %s\n", strerror(errno)); return 1; } cputotal = get_cputotal(); if(cputotal <= 0) { printf("invalid cputotal value: %d\n", cputotal); return 1; } for(i=0; i // open per-cpu file sprintf(filename, "%s%d", filename_base, i); fd = open(filename, O_RDONLY); if (fd < 0) { printf("fopen() failed: %s\n", strerror(errno)); return 1; } // read per-cpu file bytesread = read(fd, buf, MAX_BUFLEN); while(bytesread > 0) { buf[bytesread] = '\0'; puts(buf); bytesread = read(fd, buf, MAX_BUFLEN); }; // close per-cpu file if(fd > 0) { close(fd); fd = 0; } } if(umount("/mnt/relay") && (errno != EINVAL)) { printf("umount() failed: %s\n", strerror(errno)); return 1; } return 0; }
上面这个例子给出了使用relay的一个最简单的情形,并没有实际用处,但是形象描述了从用户空间和内
核空间两个方面使用relay的基本流程。实际应用中对relay的使用当然要比这复杂得多。
|