科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道Linux数据传输技术Relay的原理及实例 (2)

Linux数据传输技术Relay的原理及实例 (2)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

这些API接口向位于内核空间的用户提供了管理relay通道、数据写入等功能。下面介绍其中主要的部分,完整的API接口列表请参见这里。

作者:赛迪网技术社区 来源:赛迪网技术社区 2007年10月19日

关键字: 原理 传输 数据 Linux

  • 评论
  • 分享微博
  • 分享邮件
 

面向内核空间的 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的使用当然要比这复杂得多。更多的例子请参见relay的主页。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章