Xenomai通信机制XDDP源代码的部分学习

In the Xenomai API documentation, you have also an example of regular (i.e. non-real-time) thread and a real-time task communicating through an XDDP socket:
https://xenomai.org/documentation/xenomai-3/html/xeno3prm/xddp-echo_8c-example.html.
Your ROS node should behave as the regular thread does.

Then we would like to read this source code of regular thread for the website.

 * regular_thread---------------------------------------+  |
 *   =>  open /dev/rtp0                                 |  ^
 *   =>  read traffic from RT domain via read()         |  |
 *   =>  echo traffic back to RT domain via write()     +--+
 */
static void *regular_thread(void *arg)
{
        char buf[128], *devname;
        int fd, ret;
        if (asprintf(&devname, "/dev/rtp%d", XDDP_PORT) < 0)
                fail("asprintf");
        fd = open(devname, O_RDWR);
        free(devname);
        if (fd < 0)
                fail("open");
        for (;;) {
                /* Get the next message from realtime_thread. */
                ret = read(fd, buf, sizeof(buf));
                if (ret <= 0)
                        fail("read");
                /* Echo the message back to realtime_thread. */
                ret = write(fd, buf, ret);
                if (ret <= 0)
                        fail("write");
        }
        return NULL;
}
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define XDDP_PORT 0
 
static void fail(const char *reason)
{
    perror(reason);
    exit(EXIT_FAILURE);
}
 
int main()
{ 
    char buf[128],*devname; 
	memset(buf,0,sizeof(buf));
	int fd, ret,outwrite;
	if(asprintf(&devname,"dev/rtp%d",XDDP_PORT)<0)
	fail("asprintf");    
	fd = open("/dev/rtp0", O_RDWR); 
	free(devname);
     	if(fd<0)
	fail("open rtp0");
	for(;;){
	ret=read(fd,buf,sizeof(buf));
	if(ret <=0)
		fail("read");
 
outwrite=write(1,buf,sizeof(buf));
//puts(buf);
 
 
 
}
 
    exit(0);
}
 

这里,#define XDDP_PORT 0我们首先把通信口定义为0,static void fail()fail函数是自定义的函数。在这里详细看一下:

static void fail(const char *reason)
{
    perror(reason);
    exit(EXIT_FAILURE);
}

perror可以将函数发生的错误原因,输出到标准设备,这里输出的正是变量reason里面的字符串;exit(EXIT_FAILURE) : 代表异常退出。

char数组的用法
来源重点记住strlen和sizeof的区别以及sprintf_s(charr3, "chess%d.jpg", goodFrameCount)的使用

//char数组的用法  
     char charr1[20];  
     int num1 = strlen(charr1);//没有初始化的char数组,长度是未知的,原因是需要遇到‘\0’才结束  
       
     char charr2[] = "lilei,nihao";//编译器会自动计算长度  
     char charr3[100] = "lilei,nihao";  
     int goodFrameCount = 100;  
     sprintf_s(charr3, "chess%d.jpg", goodFrameCount);//这种用法重点学习  
     int num2 = strlen(charr3);//num2=12,strlen函数只计算可见的字符  
     int num3 = sizeof(charr3); //num3=100,sizeof计算整个数组的长度  
   
     char charr4[20];  
     //cin >> charr4;//注意两点:1、遇到空格,认为结束;  
     //cout << charr4 << endl; //2、当输入的字符串长度超过charr4的长度时,也是可以显
     //不推荐使用  
       
     cin.getline(charr4, 20);     // indicate maximum length,此种方法就可以输入包含空格的字符串了  
     cout << charr4 << endl;  

然后我们进行主函数的理解。

int main()
{ 
    char buf[128],*devname; 
	memset(buf,0,sizeof(buf));//初始化
	int fd, ret,outwrite;
	if(asprintf(&devname,"dev/rtp%d",XDDP_PORT)<0)
	fail("asprintf");    
	fd = open("/dev/rtp0", O_RDWR); 
	free(devname);
     	if(fd<0)
	fail("open rtp0");
	for(;;){
	ret=read(fd,buf,sizeof(buf));
	if(ret <=0)
		fail("read");
        outwrite=write(1,buf,sizeof(buf));
    } 
    exit(0);
}

首先是陌生的函数memset在一段内存块中填充某一个给定的值,常用于较大的对结构体和数组的清零操作学习一下用法

memset:char型初始化函数
头文件:<string.h> 或 <memory.h>
函数原型:void *memset(void *s , int ch , size_t n )
memset(结构体/数组名 , 用于替换的ASCII码对应字符 , 前n个字符 );
memset(结构体/数组名 , "用于替换的字符“ , 前n个字符 );

Description
The functions asprintf() and vasprintf() are analogs of sprintf() and vsprintf(), except that they allocate a string large enough to hold the output including the terminating null byte, and return a pointer to it via the first argument. This pointer should be passed to free() to release the allocated storage when it is no longer needed.
Return Value
When successful, these functions return the number of bytes printed, just like sprintf(). If memory allocation wasn’t possible, or some other error occurs, these functions will return -1, and the contents of strp is undefined.

如果函数失败了,那么函数返回-1,if(asprintf(&devname,"dev/rtp%d",XDDP_PORT)<0)
asprintf相对sprintf来说更安全,asprintf是动态分配memory的,不会出现memory overflow的情况,当然它的缺点是使用后需要free。free(devname);也就是说,用了aspringf一定要接上free

主要的内容读写操作在FORLOOP里面。

for(;;){
	ret=read(fd,buf,sizeof(buf));
	if(ret <=0)
		fail("read");
        outwrite=write(1,buf,sizeof(buf));
    } 

用read和write来获取和显示进程信息。

Therefore, the switch-{primary, secondary} tags denote either services which will always switch the caller to the mode mentioned, or might have to do so, depending on the context. The absence of such tag indicates that such services can complete in either modes and as such will entail no switch.

switch-{primary,secondary}标记表示始终将调用者切换到所述模式的服务,或者具体取决于上下文行动。没有这样的标记表示这类服务可以在两种模式下完成,因此不需要切换。

今日写文背景音乐《惊鸿一面》许嵩/黄龄

翻手为云覆手为雨
金盆洗手止风雨
不恋红尘却难舍回忆
每一段都有你
年少初遇常在我心
多年不减你深情
江山如画又怎能比拟
你送我的风景
柳下闻瑶琴起舞和一曲
仿佛映当年翩若惊鸿影
谁三言两语撩拨了情意
谁一颦一笑摇曳了星云
纸扇藏伏笔玄机诗文里
紫烟燃心语留香候人寻
史书列豪杰功过有几许
我今生何求惟你

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章