fifo.c
来自「俄罗斯高人Mamaich的Pocket gcc编译器(运行在PocketPC上)」· C语言 代码 · 共 450 行
C
450 行
#include <stdio.h>#include <stdarg.h>#include <string.h>#include <time.h>#include <errno.h>#include <sys/wcebase.h>#include <sys/wcetrace.h>#include <sys/wceerror.h>#include <sys/wcefile.h>#include <sys/wcememory.h>#include <sys/mqueue.h>#include <sys/fifo.h>#include <sys/keycode.h>#define MAPNAME "fifotab"#define SYSNAMELEN (32)static int master = FALSE;_devops_t _devops_fifo = { "fifo", _fifo_open, _fifo_close, _fifo_read, _fifo_write, _fifo_lseek, _fifo_ioctl };_DEVOPS _fifo_devops = &_devops_fifo;void _fifo_setmaster(){ master = TRUE;}void _fifo_setpid(void *cxt, int pid){ _FIFOIOCXT fcxt = (_FIFOIOCXT) cxt; WCETRACE(WCE_IO, "_fifo_setpid: cxt %p pid %d", cxt, pid); if (fcxt != NULL) { fcxt->pid = pid; }}int _fifo_getpid(void *cxt){ _FIFOIOCXT fcxt = (_FIFOIOCXT) cxt; WCETRACE(WCE_IO, "_fifo_getpid: cxt %p", cxt); if (fcxt != NULL) { return(fcxt->pid); } else { return(-1); }}void *_fifo_alloc(){ _FIFOIOCXT fcxt; _FIFOTAB fifotab; HANDLE mapHnd; DWORD winerr = 0; BOOL new = FALSE; char name[SYSNAMELEN]; wchar_t nameW[SYSNAMELEN]; int i; fcxt = (_FIFOIOCXT) calloc(1, sizeof(_fifoiocxt_t)); if (fcxt == NULL) { errno = ENOMEM; return(NULL); } fcxt->mqd = -1; /* Initialize our message queue descriptor */ /* Create the per-process-group fifo table */ WCETRACE(WCE_IO, "_fifo_alloc: CALLED pgid %d", getpgid(0)); sprintf(name, "%d:%s", getpgid(0), MAPNAME); mbstowcs(nameW, name, strlen(name)+1); SetLastError(0); mapHnd = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE|SEC_COMMIT, 0, sizeof(_fifotab_t), nameW); if (mapHnd == NULL) { winerr = GetLastError(); WCETRACE(WCE_IO, "_fifo_alloc: FATAL CreateFileMappingW fails winerr %d", winerr); exit(1); } if ((winerr = GetLastError()) != ERROR_ALREADY_EXISTS) { new = TRUE; } fifotab = MapViewOfFile(mapHnd, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(_fifotab_t)); if (fifotab == NULL) { winerr = GetLastError(); WCETRACE(WCE_IO, "_fifo_alloc: FATAL MapViewOfFile fails winerr %d", winerr); exit(1); } if (new) { WCETRACE(WCE_IO, "_fifo_alloc: created NEW system fifotab (%s) @%x", name, fifotab); memset(fifotab, 0, sizeof(_fifotab_t)); } else { WCETRACE(WCE_IO, "_fifo_alloc: mapped EXISTING system fifotab @%x", fifotab); } /* SYNC; */ fcxt->fifotab = fifotab; return((void *)fcxt);}/* NOTE: mqd SIMPLY MUST reside in the per-process file descriptor table - * this is because when the descs are "copied", mq_open will have to be done */int _fifo_open(struct _reent *r, const char *path, int flags, int mode, void *cxt){ struct mq_attr mqattr = { 0, MQ_MAXMSG, MQ_MSGSIZE, 0 }; char *cp; int i, fd; char fifopath[SYSNAMELEN]; char buf[SYSNAMELEN]; _fifoent_t *fifoents; _FIFOIOCXT fcxt = (_FIFOIOCXT) cxt; CXTCHECK(fd, fcxt); fifoents = fcxt->fifotab->fifotab; /* No fd specified, use next available fd */ if (strncmp(path, "fifo", 4) == 0) { if (strlen(path) == 4) { fd = -1; for (i = 0; i < MAXFIFOS; i++) { if (fifoents[i].refcnt == 0) { fd = i; sprintf(buf, "fifo%d", fd); break; } } if (fd == -1) { errno = ENMFILE; return(-1); } } else { memset(buf, 0, SYSNAMELEN); for (i = 0, cp = (char *) &path[4]; *cp != '\0'; cp++, i++) { if (!isdigit(*cp)) { errno = EINVAL; return(-1); } buf[i] = *cp; } fd = atoi(buf); WCETRACE(WCE_IO, "_fifo_open: parsed fd %d from \"%s\"", fd, path); if (fd < 0 || fd >= MAXFIFOS) { errno = EINVAL; return(-1); } strcpy(buf, path); } /* Prepend the mq name with our pgid */ sprintf(fifopath, "%d:%s", getpgid(0), buf); if (fcxt->mqd == (mqd_t) -1) { if ((fcxt->mqd = mq_open(fifopath, flags, mode, &mqattr)) == (mqd_t) - 1) { printf("_fifo_open: Unable to open message queue"); return(-1); } fcxt->refcnt = 1; } else { fcxt->refcnt++; } WCETRACE(WCE_IO, "_fifo_open: fifopath \"%s\" fcxt->mqd %d fcxt->refcnt %d\n", fifopath, fcxt->mqd, fcxt->refcnt); fifoents[fd].fd = fd; fifoents[fd].refcnt++; /* Clear the termios settings */ memset(&fcxt->termios, 0, sizeof(struct termios)); fcxt->readbuf.len = -1; WCETRACE(WCE_IO, "_fifo_open returns %d", fd); return(fd); } else { WCETRACE(WCE_IO, "_fifo_open: ERROR bogus path \"%s\"", path); errno = EINVAL; return(-1); }}int_fifo_close(struct _reent *r, int fd, void *cxt){ int retval; _fifoent_t *fifoents; _FIFOIOCXT fcxt = (_FIFOIOCXT) cxt; WCETRACE(WCE_IO, "_fifo_close %d cxt %p", fd, cxt); CXTCHECK(fd, fcxt); fifoents = fcxt->fifotab->fifotab; FIFOCHECK(fd); /* Signal the reader if we are the only writer */ if (fifoents[fd].refcnt <= 2 || master) { retval = mq_signal(fcxt->mqd, TRUE); } /* Adjust system reference count */ if (fifoents[fd].refcnt > 0) fifoents[fd].refcnt--; if (master) fifoents[fd].refcnt = 0; WCETRACE(WCE_IO, "_fifo_close: refcnt %d AFTER", fifoents[fd].refcnt); if (fcxt->refcnt > 0) { retval = 0; fcxt->refcnt--; WCETRACE(WCE_IO, "_fifo_close: fcxt refcnt %d->%d", fcxt->refcnt+1, fcxt->refcnt); } /* Close only if process refcnt (mqent) is zero */ if (fcxt->refcnt == 0) { if (fcxt->mqd != (mqd_t) -1) { retval = mq_close(fcxt->mqd); WCETRACE(WCE_IO, "_fifo_close: mq_close returns %d errno %d\n", retval, errno); fcxt->mqd = (mqd_t) -1; } /* Clear the termios settings */ memset(&fcxt->termios, 0, sizeof(struct termios)); } return(retval);}int_fifo_read(struct _reent *r, int fd, char *ptr, int len, void *cxt){ int retval, nread, ncopy; char buf[MQ_MSGSIZE]; unsigned int prio; int eol = FALSE; char *savptr; char dbgbuf[2048]; int avail, i, bufcnt, savpos, savlen, foo; _fifoent_t *fifoents; _FIFOIOCXT fcxt = (_FIFOIOCXT) cxt; WCETRACE(WCE_IO, "_fifo_read %d %p %d %p", fd, ptr, len, cxt); if (ptr == NULL) { errno = EINVAL; return(-1); } CXTCHECK(fd, fcxt); fifoents = fcxt->fifotab->fifotab; FIFOCHECK(fd); WCETRACE(WCE_IO, "_fifo_read %d %d c_oflag %d", fd, len, fcxt->termios.c_oflag); savptr = ptr; savlen = len; nread = 0; while (len > 0 && !eol) { /* A buffer is needed */ if (fcxt->readbuf.len <= 0 || fcxt->readpos > (fcxt->readbuf.len-1)) { if (nread > 0) { /* Some data has already been read: return it instead of blocking */ if (mq_msgcnt(fcxt->mqd) == 0) { break; } } /* This is the blocking read */ retval = mq_receive(fcxt->mqd, (char *)&fcxt->readbuf, MQ_MSGSIZE, &prio); WCETRACE(WCE_IO, "fifo_read: mqrecv %d", retval); if (retval == 0) { WCETRACE(WCE_IO, "fifo_read: EOF"); break; } if (retval == -1) return(retval); fcxt->readpos = 0; foo = fcxt->readbuf.len; /* printf("fifo_read: got msg len %d\n", foo); */ WCETRACE(WCE_IO, "fifo_read: got msg len %d", foo); } savpos = fcxt->readpos; /* If ICANON is set in lflag: handle DEL and assemble input line until \n */ if (fcxt->termios.c_lflag & ICANON) { ncopy = 1; WCETRACE(WCE_IO, "_fifo_read (ICANON) INCHAR %c", fcxt->readbuf.buf[fcxt->readpos]); switch (fcxt->readbuf.buf[fcxt->readpos]) { case K_DEL: WCETRACE(WCE_IO, "K_DEL: nread %d readpos %d ptr %p", nread, fcxt->readpos, ptr); ncopy = 0; fcxt->readpos++; if (nread > 0) { len++; len = (len > savlen) ? savlen : len; nread--; *ptr = '\0'; ptr--; } else { continue; } break; case '\n': case '\r': eol = TRUE; fcxt->readbuf.buf[fcxt->readpos] = '\n'; WCETRACE(WCE_IO, "_fifo_read (ICANON) eol %d", eol); break; } } else { avail = fcxt->readbuf.len - fcxt->readpos; ncopy = (len > avail) ? avail : len; } if (fcxt->termios.c_oflag) { bufcnt = _termios_cookout(ptr, &(fcxt->readbuf.buf[fcxt->readpos]), &ncopy, &fcxt->termios); len -= ncopy; fcxt->readpos += bufcnt; ptr += ncopy; nread += ncopy; } else { if (ncopy > 0) { bufcnt = ncopy; memcpy(ptr, &(fcxt->readbuf.buf[fcxt->readpos]), ncopy); len -= ncopy; fcxt->readpos += ncopy; ptr += ncopy; nread += ncopy; } } if (fcxt->termios.c_lflag & ECHO) { /* Echo only if our io context has been set up for it (startup.c) */ if (fcxt->echocxt != NULL) { _termios_echo(fcxt->echofd, &(fcxt->readbuf.buf[savpos]), bufcnt, &fcxt->termios, fcxt->echocxt); } } } if (fcxt->termios.c_lflag & ICANON && nread > 0) { dbgbuf[0] = 0; sprintf(dbgbuf, "%d ", ptr[0]); for (i = 1; i < nread; i++) { sprintf(buf, "%d ", ptr[i]); strcat(dbgbuf, buf); } WCETRACE(WCE_IO, "_fifo_read: (ICANON) INBUF %s", dbgbuf); } WCETRACE(WCE_IO, "_fifo_read: return w/nread %d\n", nread); return(nread);}int_fifo_write(struct _reent *r, int fd, char *ptr, int len, void *cxt){ int retval, nwrite; unsigned int prio = 1; _fifomsg_t msg; _fifoent_t *fifoents; _FIFOIOCXT fcxt = (_FIFOIOCXT) cxt; WCETRACE(WCE_IO, "_fifo_write %d %d %p", fd, len, cxt); CXTCHECK(fd, fcxt); fifoents = fcxt->fifotab->fifotab; FIFOCHECK(fd); if (ptr == NULL) { errno = EINVAL; return(-1); } nwrite = 0; while (len > 0) { msg.len = (len > MSG_BUFSIZE) ? MSG_BUFSIZE : len; memcpy(msg.buf, ptr, msg.len); retval= mq_send(fcxt->mqd, (char *)&msg, MQ_MSGSIZE, prio); if (retval == -1) { WCETRACE(WCE_IO, "mq_send returns %d errno %d\n", retval, errno); return(retval); } ptr += msg.len; nwrite += msg.len; len -= msg.len; } return(nwrite);}int_fifo_lseek(struct _reent *r, int fd, off_t offset, int whence, void *cxt){ errno = ENOSYS; return(-1);}int_fifo_ioctl(struct _reent *r, int fd, int request, void *cxt, ...){ va_list ap; void *argbuf = NULL; _fifoent_t *fifoents; _FIFOIOCXT fcxt = (_FIFOIOCXT) cxt; WCETRACE(WCE_IO, "_fifo_ioctl %d %d %p", fd, request, cxt); CXTCHECK(fd, fcxt); fifoents = fcxt->fifotab->fifotab; FIFOCHECK(fd); WCETRACE(WCE_IO, "_fifo_ioctl %d %d", fd, request); switch (request) { case TCGETA: case TCSETA: va_start(ap, request); argbuf = va_arg(ap, void *); va_end(ap); if (argbuf == NULL) { WCETRACE(WCE_IO, "_fifo_ioctl ERROR argbuf is NULL"); errno = EINVAL; return(-1); } if (request == TCGETA) { memcpy(argbuf, &fcxt->termios, sizeof(struct termios)); } else { memcpy(&fcxt->termios, argbuf, sizeof(struct termios)); } break; default: WCETRACE(WCE_IO, "_fifo_ioctl ERROR unimp request %d", request); errno = ENOSYS; return(-1); } WCETRACE(WCE_IO, "_fifo_ioctl SUCCESS for request %d", request); return(0);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?