snifer

[原创]ADSP-BF535 管道(Pipes)通信的实现

0
阅读(3017)

ADSP-BF535 接口丰富,性能优良,采用16位定点DSP内核,可实现300Mhz的持续工作,其中具有16个FPIO,在uclinux下可实现管道通信,具体可以:

$ ls | pr | lpr

把命令ls(列出目录中的文件)的输出通过管道连接到命令pr的标准输入上进行分页。最后,命令pr的标准输出通过管道连接到命令lpr的标准输入上,从而在缺省打印机上打印出结果。进程感觉不到这种重定向,它们和平常一样地工作。正是shell建立了进程之间的临时管道。

管道是单向的、先进先出的、无结构的、固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起。写进程在管道的尾端写入数据,读进程在管道的首端读出数据。数据读出后将从管道中移走,其它读进程都不能再读到这些数据。管道提供了简单的流控制机制。进程试图读空管道时,在有数据写入管道前,进程将一直阻塞。同样,管道已经满时,进程再试图写管道,在其它进程从管道中移走数据之前,写进程将一直阻塞,具体如下:

当写进程向管道写的时候,它使用标准的write库函数。这些库函数(read、write等)要求传递一个文件描述符作为参数。文件描述符是该文件对应的file数据结构在进程的file数据结构数组中的索引,每一个都表示一个打开的文件,在这种情况下,是打开的管道。Linux系统调用使用描述这个管道的file数据结构中f_op所指的write例程,该write例程使用表示管道的VFS I 节点中存放的信息,来管理写请求。如果共享数据页中有足够的空间能把所有的字节都写到管道中,而且管道没有被读进程锁定,则Linux就在管道上为写进程加锁,并把字节从进程的地址空间拷贝到共享数据页。如果管道被读进程锁定或者共享数据页中没有足够的空间,则当前进程被迫睡眠,它被挂在管道I节点的等待队列中等待,而后调用调度程序,让另外一个进程运行。睡眠的写进程是可以中断的(interruptible),所以它可以接收信号。当管道中有了足够的空间可以写数据,或者当锁定解除时,写进程就会被读进程唤醒。当数据写完之后,管道的VFS I 节点上的锁定解除,在管道I节点的等待队列中等待的所有读进程都会被唤醒。

根据如上所述,我们可以编程实现Pipes的通信:

#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
 int pipe_fd[2];
 pid_t pid;
 char buf_r[100];
 char* p_wbuf;
 int r_num;
 memset(buf_r,0,sizeof(buf_r));
 if(pipe(pipe_fd)<0)
 {
 printf("pipe create error\n");
 return -1;
 }
 if((pid=fork())==0)
 {
  printf("\n");
  close(pipe_fd[1]);
  sleep(2);
  if((r_num=read(pipe_fd[0],buf_r,100))>0){
   printf(   "%d numbers read from the pipe is %s\n",r_num,buf_r);
  } 
  close(pipe_fd[0]);
  exit(0);
   }
 else if(pid>0)
 {
  close(pipe_fd[0]);
  if(write(pipe_fd[1],"Hello",5)!=-1)
   printf("parent write1 success!\n");
  if(write(pipe_fd[1]," Pipe",5)!=-1)
   printf("parent write2 success!\n");
  close(pipe_fd[1]);
  sleep(3);
  waitpid(pid,NULL,0);
  exit(0);
 }
}
OK,现在我们就能在管道之间实现信息的传送,很多时候当我们把自己的想法变成现实的时候,会很有成就感,学无止境,与大家共勉。