Linux 终端I/O(如何模拟具有特定内存区域的终端读/写?)
我在嵌入式平台上工作,在那里我可以完全访问直接读/写物理内存 我还致力于非对称处理,其中有一个实时应用程序与Linux并行运行,但完全与Linux隔离 我想将消息从RT-app显示到Linux控制台(并且可能将命令从Linux发送到RT-app)。我目前的解决方案是输出从RT应用程序到串行端口的所有内容。然后,在Linux中,我将读取串行端口输入Linux 终端I/O(如何模拟具有特定内存区域的终端读/写?),linux,embedded,terminal,asymmetric,Linux,Embedded,Terminal,Asymmetric,我在嵌入式平台上工作,在那里我可以完全访问直接读/写物理内存 我还致力于非对称处理,其中有一个实时应用程序与Linux并行运行,但完全与Linux隔离 我想将消息从RT-app显示到Linux控制台(并且可能将命令从Linux发送到RT-app)。我目前的解决方案是输出从RT应用程序到串行端口的所有内容。然后,在Linux中,我将读取串行端口输入 这是可行的,但似乎没有必要,因为RT应用程序和Linux在同一台物理机器上。回想一下串行端口是如何工作的,它有一个内存缓冲区,应用程序可以读/写该缓冲
这是可行的,但似乎没有必要,因为RT应用程序和Linux在同一台物理机器上。回想一下串行端口是如何工作的,它有一个内存缓冲区,应用程序可以读/写该缓冲区。因此,我想知道是否可以将终端显示器连接到特定的内存区域(即0x10000),并且当RT app将某条消息“打印”到0x10000时,Linux终端会显示该消息 您可以使用“邮箱”技术构造一种虚拟串行端口。我将描述一个简单的工作连接的一半,您可能希望每个方向都有一个这样的连接,这样您就可以发送命令并获得响应 在内核初始化期间保留一块内存。比方说4k,因为这通常是一个页面,但256字节甚至16字节也可以。为另一个方向预留一秒钟 当频道的“编剧”想说些什么时,它首先检查前32位字是否为零。如果是,则从第5个字节开始,它写入消息-文本或二进制数据,无论什么,最大值为4k-4=4092字节。然后,它将第一个字设置为它已写入的字节数 接收器观察它正在接收的通道的第一个字中的字节计数。当它看到一个非零字节计数时,它从内存中读取那么多字节。然后,它将字节计数设置为零,以向编写器表示现在可以方便地编写新消息 这取决于您实际访问实际内存或通过同一缓存工作,并且您有一个用于写入字节计数的原子写入操作(如果您没有32位原子写入,则使用16位计数,无论如何这是足够的,或者使缓冲区更小并使用8位计数)。由于编写器只能在其为零时将其设置为非零值,而读者只能在其为非零时将其设置为零值,因此所有这些都是可行的 这当然是一个简单的机制,任何一方都可能被另一方阻止。但是您可以设计源消息的组件来考虑这一点。您还可以通过提出一种方法来扩展它,使多条消息处于飞行状态,或者并行添加额外的优先级或错误报告通道
哦,在你开始编写代码之前,先做一些网络搜索。我确信已经有了这样的机制或其他机制来连接RT和linux组件。但是,如果你在一个没有为你提供功能的操作系统的小型嵌入式系统上遇到这种问题,学习自己做这件事也很有意思,而且是必要的。在linux中有几种执行IPC的方法,通常都涉及到文件描述符。在我看来,你最好的办法是继续做你正在做的事情,正如你所说的,这可能是过火了,但尝试实现你自己的共享内存解决方案肯定是更过火了 编辑: 正如评论中提到的,您正在运行一个实时进程这一事实让事情变得糟糕,而本地IPC可能不是您的最佳选择这是一篇我刚刚在谷歌上搜索到的文章,它似乎提供了你想要的答案 如果您不想全部读取,它建议您使用FIFO或共享内存作为并发原语,具体取决于您需要的通信类型。从个人经验来看,FIFO从长远来看会减少麻烦,因为您不必太担心同步问题
如果您想在终端中监控程序,您很可能必须编写一个从fifo/共享内存读取并向stdout发送消息的小程序。我已经成功地使用共享内存fifo系统在进程之间进行通信(尽管与您的情况不同)。关键是只有一个线程可以是生产者,而一个线程可以是消费者。您还需要确保,正如Chris Stratton提到的,使用适当的内存屏障正确处理任何缓存。Linux对于内存障碍有一个非常直接的API,我不知道你的实时应用程序可能有什么可用的。我试着找出哪些地方可能需要记忆障碍 以下是一个未经测试(且完全未优化)的共享fifo实现。您的RT应用程序可以向fifo写入字符,Linux应用程序或驱动程序可以从fifo中读取字符。理想情况下,您将拥有一种机制,用于向Linux端发送数据准备就绪的信号(可能是一个未使用的GPIO,它可以在RT端插入时触发中断?)。否则,Linux端可以在fifo中轮询数据,但由于通常的原因,这可能不太理想
struct fifo {
char volatile* buf;
int buf_len;
int volatile head; // index to first char in the fifo
int volatile tail; // index to next empty slot in fifo
// if (head == tail) then fifo is empty
// if (tail < head) the fifo has 'wrapped'
};
void fifo_init( struct fifo* pFifo, char* buf, int buf_len)
{
pFifo->buf = buf;
pFifo->buf_len = buf_len;
pFifo->head = 0;
pFifo->tail = 0;
}
int fifo_is_full( struct fifo* pFifo)
{
int head;
int tail;
// a read barrier may be required here
head = pFifo->head;
tail = pFifo->tail;
// fifo is full if ading another char would cause
// tail == head
++tail;
if (tail == pFifo->buf_len) {
tail = 0;
}
return (tail == head);
}
int fifo_is_empty( struct fifo* pFifo)
{
int head;
int tail;
// a read barrier may be required here
head = pFifo->head;
tail = pFifo->tail;
return head == tail;
}
// this function is the only one that modifies
// the pFifo->tail index. It can only be used
// by a single writer thread.
int fifo_putchar( struct fifo* pFifo, char c)
{
int tail = pFifo->tail;
if (fifo_is_full(pFifo)) return 0;
pFifo->buf[tail] = c;
++tail;
if (tail == pFifo->buf_len) {
tail = 0;
}
//note: the newly placed character isn't actually 'in' the fifo
// as far as the reader thread is concerned until the following
// statement is run
pFifo->tail = tail;
// a write barrier may need to be placed here depending on
// the system. Microsoft compilers place a barrier by virtue of
// the volatile keyword, on a Linux system a `wmb()` may be needed
// other systems will have other requirements
return 1;
}
// this function is the only one that modified the
// pFifo->head index. It can only be used by a single
// reader thread.
int fifo_getchar( struct fifo* pFifo, char* pC)
{
char c;
int head = pFifo->head;
if (fifo_is_empty(pFifo)) return 0;
// a read barrier may be required here depending on the system
c = pFifo->buf[head];
++head;
if (head == pFifo->buf_len) {
head = 0;
}
// as far as the write thread is concerned, the char
// hasn't been removed until this statement is executed
pFifo->head = head;
// a write barrier might be required
*pC = c;
return 1;
}
struct-fifo{
煤焦挥发分*buf;
布夫伦国际酒店;
int volatile head;//fifo中第一个字符的索引
int volatile tail;//索引到fifo中的下一个空插槽
//如果(head==tail),则fifo为空
//如果(尾<头)fifo已“包装”
};
void fifo_init(结构fifo*pFifo,字符*buf,整数buf_len)
{
pFifo->buf=buf;
pFifo->buf_len=buf_len;
pFifo->水头=0;
pFifo->tail=0;
}
int fifo已满(结构fifo*pFifo)
{
int头;
内尾;
//此处可能需要读屏障
头部=pFifo->头部;
tail=pFifo->tail;
//如果出现另一个cha,则fifo已满