面向內(nèi)核空間的 API
這些API接口向位于內(nèi)核空間的用戶提供了管理relay通道、數(shù)據(jù)寫入等功能。下面介紹其中主要的部分,完整的API接口列表請參見這里。
●relay_open() - 創(chuàng)建一個relay通道,包括創(chuàng)建每個CPU對應(yīng)的relay緩沖區(qū)。
●relay_close() - 關(guān)閉一個relay通道,包括釋放所有的relay緩沖區(qū),在此之前會調(diào)用relay_switch()來處理這些relay緩沖區(qū)以保證已讀取但是未滿的數(shù)據(jù)不會丟失
●relay_write() - 將數(shù)據(jù)寫入到當(dāng)前CPU對應(yīng)的relay緩沖區(qū)內(nèi)。由于它使用了local_irqsave()保護(hù),因此也可以在中斷上下文中使用。
●relay_reserve() - 在relay通道中保留一塊連續(xù)的區(qū)域來留給未來的寫入操作。這通常用于那些希望直接寫入到relay緩沖區(qū)的用戶??紤]到性能或者其它因素,這些用戶不希望先把數(shù)據(jù)寫到一個臨時緩沖區(qū)中,然后再通過relay_write()進(jìn)行寫入。
Relay的例子
我們用一個***簡單的例子來介紹怎么使用Relay。這個例子由兩部分組成:一部分是位于內(nèi)核空間將數(shù)據(jù)寫入relay文件的程序,使用時需要作為一個內(nèi)核模塊被加載;另一部分是位于用戶空間從relay文件中讀取數(shù)據(jù)的程序,使用時作為普通用戶態(tài)程序運(yùn)行。
內(nèi)核空間的程序主要操作是:
加載模塊時,打開一個relay通道,并且往打開的relay通道中寫入消息;
卸載模塊時,關(guān)閉relay通道。
程序內(nèi)容:
/*
* 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");
用戶空間的函數(shù)主要操作是:
●如果relayfs文件系統(tǒng)還沒有被mount,則將其mount到目錄/mnt/relay上;
●遍歷每一個CPU對應(yīng)的緩沖文件;
●打開文件;
●讀取所有文件內(nèi)容;
●關(guān)閉文件;
●***后,umount掉relay文件系統(tǒng)。
程序內(nèi)容:
/*
* 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的一個***簡單的情形,并沒有實際用處,但是形象描述了從用戶空間和內(nèi)核空間兩個方面使用relay的基本流程。實際應(yīng)用中對relay的使用當(dāng)然要比這復(fù)雜得多。更多的例子請參見relay的主頁。(T002)