📄 fifo.c
字号:
/* @(#)fifo.c 1.21 99/12/29 Copyright 1989,1997 J. Schilling */#ifndef lintstatic char sccsid[] = "@(#)fifo.c 1.21 99/12/29 Copyright 1989,1997 J. Schilling";#endif/* * A "fifo" that uses shared memory between two processes * * The actual code is a mixture of borrowed code from star's fifo.c * and a proposal from Finn Arne Gangstad <finnag@guardian.no> * who had the idea to use a ring buffer to handle average size chunks. * * Copyright (c) 1989,1997 J. Schilling *//* * 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, 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; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#define DEBUG/*#define XDEBUG*/#include <mconfig.h>#if !defined(HAVE_SMMAP) && !defined(HAVE_USGSHM) && !defined(HAVE_DOSALLOCSHAREDMEM)#undef FIFO /* We cannot have a FIFO on this platform */#endif#ifdef FIFO#if !defined(USE_MMAP) && !defined(USE_USGSHM)#define USE_MMAP#endif#ifndef HAVE_SMMAP# undef USE_MMAP# define USE_USGSHM /* now SYSV shared memory is the default*/#endif#ifdef USE_MMAP /* Only want to have one implementation */# undef USE_USGSHM /* mmap() is preferred */#endif#ifdef HAVE_DOSALLOCSHAREDMEM /* This is for OS/2 */# undef USE_MMAP# undef USE_USGSHM# define USE_OS2SHM#endif#include <fctldefs.h>#include <sys/types.h>#if defined(HAVE_SMMAP) && defined(USE_MMAP)#include <sys/mman.h>#endif#include <stdio.h>#include <stdxlib.h>#include <unixstd.h>#include <waitdefs.h>#include <utypes.h>#include <standard.h>#include <errno.h>#include <signal.h>#include <libport.h>#include "cdrecord.h"#ifdef DEBUG#ifdef XDEBUGFILE *ef;#define USDEBUG1 if (debug) {if(s == owner_reader)fprintf(ef, "r");else fprintf(ef, "w");fflush(ef);}#define USDEBUG2 if (debug) {if(s == owner_reader)fprintf(ef, "R");else fprintf(ef, "W");fflush(ef);}#else#define USDEBUG1#define USDEBUG2#endif#define EDEBUG(a) if (debug) error a#else#define EDEBUG(a)#define USDEBUG1#define USDEBUG2#endif#define palign(x, a) (((char *)(x)) + ((a) - 1 - (((unsigned)((x)-1))%(a))))typedef enum faio_owner { owner_none, owner_reader, owner_writer, owner_faio} fowner_t;char *onames[] = { "none", "reader", "writer", "faio"};typedef struct faio { int len; volatile fowner_t owner; short fd; short saved_errno; char *bufp;} faio_t;struct faio_stats { long puts; long gets; long empty; long full; long done; long cont_low;} *sp;#define MIN_BUFFERS 3#define MSECS 1000#define SECS (1000*MSECS)/* * Note: WRITER_MAXWAIT & READER_MAXWAIT need to be greater than the SCSI * timeout for commands that write to the media. This is currently 200s * if we are in SAO mode. *//* microsecond delay between each buffer-ready probe by writing process */#define WRITER_DELAY (20*MSECS)#define WRITER_MAXWAIT (240*SECS) /* 240 seconds max wait for data *//* microsecond delay between each buffer-ready probe by reading process */#define READER_DELAY (80*MSECS)#define READER_MAXWAIT (240*SECS) /* 240 seconds max wait for reader */LOCAL char *buf;LOCAL char *bufbase;LOCAL char *bufend;LOCAL long buflen;extern int debug;extern int lverbose;EXPORT void init_fifo __PR((long));#ifdef USE_MMAPLOCAL char* mkshare __PR((int size));#endif#ifdef USE_USGSHMLOCAL char* mkshm __PR((int size));#endif#ifdef USE_OS2SHMLOCAL char* mkos2shm __PR((int size));#endifEXPORT BOOL init_faio __PR((int tracks, track_t *track, int));EXPORT BOOL await_faio __PR((void));EXPORT void kill_faio __PR((void));EXPORT int wait_faio __PR((void));LOCAL void faio_reader __PR((int tracks, track_t *track));LOCAL void faio_read_track __PR((track_t *trackp));LOCAL void faio_wait_on_buffer __PR((faio_t *f, fowner_t s, unsigned long delay, unsigned long max_wait));LOCAL int faio_read_segment __PR((int fd, faio_t *f, int len));LOCAL faio_t *faio_ref __PR((int n));EXPORT int faio_read_buf __PR((int f, char *bp, int size));EXPORT int faio_get_buf __PR((int f, char **bpp, int size));EXPORT void fifo_stats __PR((void));EXPORT int fifo_percent __PR((BOOL addone));EXPORT voidinit_fifo(fs) long fs;{ int pagesize; if (fs == 0L) return;#ifdef _SC_PAGESIZE pagesize = sysconf(_SC_PAGESIZE);#else pagesize = getpagesize();#endif buflen = roundup(fs, pagesize) + pagesize; EDEBUG(("fs: %ld buflen: %ld\n", fs, buflen));#if defined(USE_MMAP) buf = mkshare(buflen);#endif#if defined(USE_USGSHM) buf = mkshm(buflen);#endif#if defined(USE_OS2SHM) buf = mkos2shm(buflen);#endif bufbase = buf; bufend = buf + buflen; EDEBUG(("buf: %X bufend: %X, buflen: %ld\n", buf, bufend, buflen)); buf = palign(buf, pagesize); buflen -= buf - bufbase; EDEBUG(("buf: %X bufend: %X, buflen: %ld (align %ld)\n", buf, bufend, buflen, buf - bufbase)); /* * Dirty the whole buffer. This can die with various signals if * we're trying to lock too much memory */ fillbytes(buf, buflen, '\0');#ifdef XDEBUG if (debug) ef = fopen("/tmp/ef", "w");#endif}#ifdef USE_MMAPLOCAL char *mkshare(size) int size;{ int f; char *addr;#ifdef MAP_ANONYMOUS /* HP/UX */ f = -1; addr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, f, 0);#else if ((f = open("/dev/zero", O_RDWR)) < 0) comerr("Cannot open '/dev/zero'.\n"); addr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, f, 0);#endif if (addr == (char *)-1) comerr("Cannot get mmap for %d Bytes on /dev/zero.\n", size); close(f); if (debug) errmsgno(EX_BAD, "shared memory segment attached: %x\n", addr); return (addr);}#endif#ifdef USE_USGSHM#include <sys/ipc.h>#include <sys/shm.h>LOCAL char *mkshm(size) int size;{ int id; char *addr; /* * Unfortunately, a declaration of shmat() is missing in old * implementations such as AT&T SVr0 and SunOS. * We cannot add this definition here because the return-type * changed on newer systems. * * We will get a warning like this: * * warning: assignment of pointer from integer lacks a cast * or * warning: illegal combination of pointer and integer, op = *//* extern char *shmat();*/ if ((id = shmget(IPC_PRIVATE, size, IPC_CREAT|0600)) == -1) comerr("shmget failed\n"); if (debug) errmsgno(EX_BAD, "shared memory segment allocated: %d\n", id); if ((addr = shmat(id, (char *)0, 0600)) == (char *)-1) comerr("shmat failed\n"); if (debug) errmsgno(EX_BAD, "shared memory segment attached: %x\n", addr); if (shmctl(id, IPC_RMID, 0) < 0) comerr("shmctl failed to detach shared memory segment\n");#ifdef SHM_LOCK /* * Although SHM_LOCK is standard, it seems that all versions of AIX * ommit this definition. */ if (shmctl(id, SHM_LOCK, 0) < 0) comerr("shmctl failed to lock shared memory segment\n");#endif return (addr);}#endif#ifdef USE_OS2SHMLOCAL char *mkos2shm(size) int size;{ char *addr; /* * The OS/2 implementation of shm (using shm.dll) limits the size of one shared * memory segment to 0x3fa000 (aprox. 4MBytes). Using OS/2 native API we have * no such restriction so I decided to use it allowing fifos of arbitrary size. */ if(DosAllocSharedMem(&addr,NULL,size,0X100L | 0x1L | 0x2L | 0x10L)) comerr("DosAllocSharedMem() failed\n"); if (debug) errmsgno(EX_BAD, "shared memory allocated at address: %x\n", addr); return (addr);}#endifLOCAL int faio_buffers;LOCAL int faio_buf_size;LOCAL int buf_idx;LOCAL pid_t faio_pid;LOCAL BOOL faio_didwait;/*#define faio_ref(n) (&((faio_t *)buf)[n])*/EXPORT BOOLinit_faio(tracks, track, bufsize) int tracks; track_t *track; int bufsize;{ int n; faio_t *f; int pagesize; char *base; if (buflen == 0L) return (FALSE);#ifdef _SC_PAGESIZE pagesize = sysconf(_SC_PAGESIZE);#else pagesize = getpagesize();#endif faio_buf_size = bufsize; f = (faio_t *)buf; /* * Compute space for buffer headers. * Round bufsize up to pagesize to make each FIFO segment * properly page aligned. */ bufsize = roundup(bufsize, pagesize); faio_buffers = (buflen - sizeof(*sp)) / bufsize; EDEBUG(("bufsize: %d buffers: %d hdrsize %d\n", bufsize, faio_buffers, faio_buffers * sizeof(struct faio))); /* * Reduce buffer space by header space. */ n = sizeof(*sp) + faio_buffers * sizeof(struct faio); n = roundup(n, pagesize); faio_buffers = (buflen-n) / bufsize; EDEBUG(("bufsize: %d buffers: %d hdrsize %d\n", bufsize, faio_buffers, faio_buffers * sizeof(struct faio))); if (faio_buffers < MIN_BUFFERS) { errmsgno(EX_BAD, "write-buffer too small, minimum is %dk. Disabling.\n", MIN_BUFFERS*bufsize/1024); return (FALSE); } if (debug) printf("Using %d buffers of %d bytes.\n", faio_buffers, faio_buf_size); f = (faio_t *)buf; base = buf + roundup(sizeof(*sp) + faio_buffers * sizeof(struct faio), pagesize); for (n = 0; n < faio_buffers; n++, f++, base += bufsize) { /* Give all the buffers to the reader process */ f->owner = owner_writer; f->bufp = base; f->fd = -1; } sp = (struct faio_stats *)f; /* point past headers */ sp->gets = sp->puts = sp->done = 0L; faio_pid = fork(); if (faio_pid < 0) comerr("fork(2) failed");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -