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}標記表示始終將調用者切換到所述模式的服務,或者具體取決於上下文行動。沒有這樣的標記表示這類服務可以在兩種模式下完成,因此不需要切換。

今日寫文背景音樂《驚鴻一面》許嵩/黃齡

翻手爲雲覆手爲雨
金盆洗手止風雨
不戀紅塵卻難捨回憶
每一段都有你
年少初遇常在我心
多年不減你深情
江山如畫又怎能比擬
你送我的風景
柳下聞瑤琴起舞和一曲
彷彿映當年翩若驚鴻影
誰三言兩語撩撥了情意
誰一顰一笑搖曳了星雲
紙扇藏伏筆玄機詩文裏
紫煙燃心語留香候人尋
史書列豪傑功過有幾許
我今生何求惟你

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