⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pipe.c

📁 xenomai 很好的linux实时补丁
💻 C
📖 第 1 页 / 共 3 页
字号:
/** * @file * This file is part of the Xenomai project. * * @note Copyright (C) 2004 Philippe Gerum <rpm@xenomai.org>  * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * \ingroup pipe *//*! * \ingroup native * \defgroup pipe Message pipe services. * * Message pipe services. * * A message pipe is a two-way communication channel between Xenomai * tasks and standard Linux processes using regular file I/O * operations on a pseudo-device. Pipes can be operated in a * message-oriented fashion so that message boundaries are preserved, * and also in byte streaming mode from real-time to standard Linux * processes for optimal throughput. * * Xenomai tasks open their side of the pipe using the rt_pipe_create() * service; standard Linux processes do the same by opening one of the * /dev/rtpN special devices, where N is the minor number agreed upon * between both ends of each pipe. Additionally, named pipes are * available through the registry support, which automatically creates * a symbolic link from entries under /proc/xenomai/registry/pipes/ to * the corresponding special device file. * *@{*/#include <nucleus/pod.h>#include <nucleus/heap.h>#include <nucleus/registry.h>#include <native/pipe.h>static int __pipe_flush_apc;static DECLARE_XNQUEUE(__pipe_flush_q);#ifdef CONFIG_XENO_EXPORT_REGISTRYstatic ssize_t __pipe_link_proc (char *buf,				 int count,				 void *data){    RT_PIPE *pipe = (RT_PIPE *)data;    return snprintf(buf,count,"/dev/rtp%d",pipe->minor);}extern xnptree_t __native_ptree;static xnpnode_t __pipe_pnode = {    .dir = NULL,    .type = "pipes",    .entries = 0,    .link_proc = &__pipe_link_proc,    .root = &__native_ptree,};#elif defined(CONFIG_XENO_OPT_REGISTRY)static xnpnode_t __pipe_pnode = {    .type = "pipes"};#endif /* CONFIG_XENO_EXPORT_REGISTRY */static void __pipe_flush_pool (xnheap_t *heap,                               void *poolmem,                               u_long poolsize,                               void *cookie){    xnarch_sysfree(poolmem,poolsize);}static inline ssize_t __pipe_flush (RT_PIPE *pipe){    ssize_t nbytes = pipe->fillsz + sizeof(RT_PIPE_MSG);    void *buffer = pipe->buffer;    pipe->buffer = NULL;    pipe->fillsz = 0;    return xnpipe_send(pipe->minor,buffer,nbytes,P_NORMAL);    /* The buffer will be freed by the output handler. */}static void __pipe_flush_handler (void *cookie){    xnholder_t *holder;    spl_t s;    xnlock_get_irqsave(&nklock,s);    /* Flush all pipes with pending messages. */    while ((holder = getq(&__pipe_flush_q)) != NULL)	{	RT_PIPE *pipe = link2rtpipe(holder);	__clear_bit(0,&pipe->flushable);	xnlock_put_irqrestore(&nklock,s);	__pipe_flush(pipe);	/* Cannot do anything upon error here. */	xnlock_get_irqsave(&nklock,s);	}    xnlock_put_irqrestore(&nklock,s);}static void *__pipe_alloc_handler (int bminor,				   size_t size,				   void *cookie){    RT_PIPE *pipe = (RT_PIPE *)cookie;    /* Allocate memory for the incoming message. */    return xnheap_alloc(pipe->bufpool,size);}static int __pipe_output_handler (int bminor,				  xnpipe_mh_t *mh,				  int retval,				  void *cookie){    RT_PIPE *pipe = (RT_PIPE *)cookie;    /* Free memory from output/discarded message. */    xnheap_free(pipe->bufpool,mh);    return retval;}int __native_pipe_pkg_init (void){    __pipe_flush_apc = rthal_apc_alloc("pipe_flush",&__pipe_flush_handler,NULL);    if (__pipe_flush_apc < 0)	return __pipe_flush_apc;    return 0;}void __native_pipe_pkg_cleanup (void){    rthal_apc_free(__pipe_flush_apc);}/** * @fn int rt_pipe_create(RT_PIPE *pipe,const char *name,int minor, size_t poolsize) * @brief Create a message pipe. * * This service opens a bi-directional communication channel allowing * data exchange between Xenomai tasks and standard Linux * processes. Pipes natively preserve message boundaries, but can also * be used in byte stream mode from Xenomai tasks to standard Linux * processes. * * rt_pipe_create() always returns immediately, even if no Linux * process has opened the associated special device file yet. On the * contrary, the non real-time side could block upon attempt to open * the special device file until rt_pipe_create() is issued on the * same pipe from a Xenomai task, unless O_NONBLOCK has been specified to * the open(2) system call. * * @param pipe The address of a pipe descriptor Xenomai will use to store * the pipe-related data.  This descriptor must always be valid while * the pipe is active therefore it must be allocated in permanent * memory. * * @param name An ASCII string standing for the symbolic name of the * message pipe. When non-NULL and non-empty, this string is copied to * a safe place into the descriptor, and passed to the registry * package if enabled for indexing the created pipe. * * Named pipes are supported through the use of the registry. When the * registry support is enabled, passing a valid @a name parameter when * creating a message pipe subsequently allows standard Linux * processes to follow a symbolic link from * /proc/xenomai/registry/pipes/@a name in order to reach the * associated special device (i.e. /dev/rtp*), so that the specific @a * minor information does not need to be known from those processes * for opening the proper device file. In such a case, both sides of * the pipe only need to agree upon a symbolic name to refer to the * same data path, which is especially useful whenever the @a minor * number is picked up dynamically using an adaptive algorithm, such * as passing P_MINOR_AUTO as @a minor value. * * @param minor The minor number of the device associated with the * pipe.  Passing P_MINOR_AUTO causes the minor number to be * auto-allocated. In such a case, the @a name parameter must be valid * so that user-space processes may subsequently follow the symbolic * link that will be automatically created from * /proc/xenomai/registry/pipes/@a name to the allocated pipe device * entry (i.e. /dev/rtp*). * * @param poolsize Specifies the size of a dedicated buffer pool for the * pipe. Passing 0 means that all message allocations for this pipe are * performed on the system heap. * * @return 0 is returned upon success. Otherwise: * * - -ENOMEM is returned if the system fails to get enough dynamic * memory from the global real-time heap in order to register the * pipe. * * - -EEXIST is returned if the @a name is already in use by some * registered object. * * - -ENODEV is returned if @a minor is different from P_MINOR_AUTO * and is not a valid minor number for the pipe special device either * (i.e. /dev/rtp*). * * - -EBUSY is returned if @a minor is already open. * * - -EPERM is returned if this service was called from an * asynchronous context. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task * * Rescheduling: possible. */int rt_pipe_create (RT_PIPE *pipe,		    const char *name,		    int minor,		    size_t poolsize){    int err = 0;    void *poolmem;    if (!xnpod_root_p())	return -EPERM;    pipe->buffer = NULL;    pipe->bufpool = &kheap;    pipe->fillsz = 0;    pipe->flushable = 0;    pipe->handle = 0;    /* i.e. (still) unregistered pipe. */    pipe->magic = XENO_PIPE_MAGIC;    xnobject_copy_name(pipe->name,name);    if (poolsize > 0)        {        /* Make sure we won't hit trivial argument errors when calling           xnheap_init(). */        if (poolsize < 2 * PAGE_SIZE)            poolsize = 2 * PAGE_SIZE;        /* Account for the overhead so that the actual free space is large           enough to match the requested size. */        poolsize += xnheap_overhead(poolsize,PAGE_SIZE);        poolsize = PAGE_ALIGN(poolsize);        poolmem = xnarch_sysalloc(poolsize);        if (!poolmem)            return -ENOMEM;        err = xnheap_init(&pipe->privpool,                          poolmem,                          poolsize,                          PAGE_SIZE); /* Use natural page size */        if (err)            {            xnarch_sysfree(poolmem,poolsize);            return err;            }        pipe->bufpool = &pipe->privpool;        }    minor = xnpipe_connect(minor,			 &__pipe_output_handler,			 NULL,			 &__pipe_alloc_handler,			 pipe);    if (minor < 0)        {        if (pipe->bufpool == &pipe->privpool)            xnheap_destroy(&pipe->privpool,__pipe_flush_pool,NULL);        return minor;        }    pipe->minor = minor;#ifdef CONFIG_XENO_OPT_PERVASIVE    pipe->cpid = 0;#endif /* CONFIG_XENO_OPT_PERVASIVE */#ifdef CONFIG_XENO_OPT_REGISTRY    /* <!> Since xnregister_enter() may reschedule, only register       complete objects, so that the registry cannot return handles to       half-baked objects... */    if (name)        {	xnpnode_t *pnode = &__pipe_pnode;		if (!*name)	    {	    /* Since this is an anonymous object (empty name on entry)	       from user-space, it gets registered under an unique	       internal name but is not exported through /proc. */	    xnobject_create_name(pipe->name,sizeof(pipe->name),(void*)pipe);	    pnode = NULL;	    }	            err = xnregistry_enter(pipe->name,pipe,&pipe->handle,pnode);        if (err)            rt_pipe_delete(pipe);        }#endif /* CONFIG_XENO_OPT_REGISTRY */    return err;}/** * @fn int rt_pipe_delete(RT_PIPE *pipe) * * @brief Delete a message pipe. * * This service deletes a pipe previously created by rt_pipe_create(). * Data pending for transmission to non real-time processes are lost. * * @param pipe The descriptor address of the affected pipe. * * @return 0 is returned upon success. Otherwise: * * - -EINVAL is returned if @a pipe is not a pipe descriptor. * * - -EIDRM is returned if @a pipe is a closed pipe descriptor. * * - -ENODEV or -EBADF can be returned if @a pipe is scrambled. * * - -EPERM is returned if this service was called from an * asynchronous context. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task * * Rescheduling: possible.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -