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

📄 fifo.c

📁 另一种方法编辑刻录程序的代码!要的与偶联系呀
💻 C
字号:
/* @(#)fifo.c	1.12 98/10/17 Copyright 1989,1997 J. Schilling */#ifndef lintstatic	char sccsid[] =	"@(#)fifo.c	1.12 98/10/17 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#include <mconfig.h>#if HAVE_MMAP#	define	USE_MMAP	1#	undef   USE_USGSHM#elif HAVE_SHMAT#	undef	USE_MMAP#	define	USE_USGSHM	1#endif#if USE_MMAP || USE_USGSHM#include <sys/types.h>#ifdef USE_MMAP#include <sys/mman.h>#endif#include <stdio.h>#include <stdlib.h>#include <unixstd.h>#include <fcntl.h>#include <utypes.h>#include <standard.h>#include <errno.h>#include <signal.h>#include "cdrecord.h"#ifdef DEBUG#define	EDEBUG(a)	if (debug) error a#else#define	EDEBUG(a)#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)/* microsecond delay between each buffer-ready probe by writing process */#define	WRITER_DELAY	(20*MSECS)#define	WRITER_MAXWAIT	(120*SECS)	/* 120 seconds max wait for data *//* microsecond delay between each buffer-ready probe by reading process */#define	READER_DELAY	(80*MSECS)#define	READER_MAXWAIT	(120*SECS)	/* 120 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));#endifEXPORT	BOOL	init_faio	__PR((int tracks, track_t *track, int));EXPORT	BOOL	await_faio	__PR((void));EXPORT	void	kill_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	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	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);}#endifLOCAL	int	faio_buffers;LOCAL	int	faio_buf_size;LOCAL	int	buf_idx;LOCAL	pid_t	faio_pid;/*#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.	 */	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");	if (faio_pid == 0) {		/* child process */		raisepri(1);		/* almost max priority */		faio_reader(tracks, track);		/* NOTREACHED */	} else {		/* close all file-descriptors that only the child will use */		for (n = 1; n <= tracks; n++)			close(track[n].f);	}	return (TRUE);}EXPORT BOOLawait_faio(){	int	n;	int	lastfd = -1;	faio_t	*f;	/*	 * Wait until the reader is active and has filled the buffer.	 */	if (lverbose || debug) {		printf("Waiting for reader process to fill input-buffer ... ");		flush();	}	faio_wait_on_buffer(faio_ref(faio_buffers - 1), owner_reader,			    500*MSECS, 0);	if (lverbose || debug)		printf("input-buffer ready.\n");	sp->empty = sp->full = 0L;	/* set correct stat state */	sp->cont_low = faio_buffers;	/* set cont to max value  */	f = faio_ref(0);	for (n = 0; n < faio_buffers; n++, f++) {		if (f->fd != lastfd &&			f->fd == STDIN_FILENO && f->len == 0) {			errmsgno(EX_BAD, "Premature EOF on stdin.\n");			kill(faio_pid, SIGKILL);			return (FALSE);		}		lastfd = f->fd;	}	return (TRUE);}EXPORT voidkill_faio(){	kill(faio_pid, SIGKILL);}LOCAL voidfaio_reader(tracks, track)	int	tracks;	track_t	*track;{	/* This function should not return, but _exit. */	int	trackno;	if (debug)		printf("\nfaio_reader starting\n");	for (trackno = 1; trackno <= tracks; trackno++) {		if (debug)			printf("\nfaio_reader reading track %d\n", trackno);		faio_read_track(&track[trackno]);	}	sp->done++;	if (debug)		printf("\nfaio_reader all tracks read, exiting\n");	/* Prevent hang if buffer is larger than all the tracks combined */	if (sp->gets == 0)		faio_ref(faio_buffers - 1)->owner = owner_reader;	_exit(0);}#ifndef	faio_refLOCAL faio_t *faio_ref(n)	int	n;{	return (&((faio_t *)buf)[n]);}#endifLOCAL voidfaio_read_track(trackp)	track_t *trackp;{	int	fd = trackp->f;	int	bytespt = trackp->secsize * trackp->secspt;	int	l;	long	tracksize = trackp->tracksize;	long	bytes_read = 0L;	long	bytes_to_read;	if (bytespt > faio_buf_size) {		comerrno(EX_BAD,		"faio_read_track fatal: secsize %d secspt %d, bytespt(%d) > %d !!\n",			 trackp->secsize, trackp->secspt, bytespt,			 faio_buf_size);	}	do {		bytes_to_read = bytespt;		if (tracksize > 0) {			bytes_to_read = tracksize - bytes_read;			if (bytes_to_read > bytespt)				bytes_to_read = bytespt;		}		l = faio_read_segment(fd, faio_ref(buf_idx), bytes_to_read);		if (++buf_idx >= faio_buffers)			buf_idx = 0;		if (l <= 0)			break;		bytes_read += l;	} while (tracksize < 0 || bytes_read < tracksize);	close(fd);	/* Don't keep files open longer than neccesary */}LOCAL voidfaio_wait_on_buffer(f, s, delay, max_wait)	faio_t	*f;	fowner_t s;	unsigned long delay;	unsigned long max_wait;{	unsigned long max_loops;	if (f->owner == s)		return;		/* return immediately if the buffer is ours */	if (s == owner_reader)		sp->empty++;	else		sp->full++;	max_loops = max_wait / delay + 1;	while (max_wait == 0 || max_loops--) {		usleep(delay);		if (f->owner == s)			return;	}	if (debug) {		errmsgno(EX_BAD,		"%lu microseconds passed waiting for %d current: %d idx: %d\n",		max_wait, s, f->owner, (f - faio_ref(0))/sizeof(*f));	}	comerrno(EX_BAD, "faio_wait_on_buffer for %s timed out.\n",	(s > owner_faio || s < owner_none) ? "bad_owner" : onames[s]);}LOCAL intfaio_read_segment(fd, f, len)	int	fd;	faio_t	*f;	int	len;{	int l;	faio_wait_on_buffer(f, owner_writer, WRITER_DELAY, WRITER_MAXWAIT);	f->fd = fd;	l = read_buf(fd, f->bufp, len);	f->len = l;	f->saved_errno = errno;	f->owner = owner_reader;	sp->puts++;	return l;}EXPORT intfaio_read_buf(fd, bp, size)	int fd;	char *bp;	int size;{	char *bufp;	int len = faio_get_buf(fd, &bufp, size);	if (len > 0) {		movebytes(bufp, bp, len);	}	return len;}EXPORT intfaio_get_buf(fd, bpp, size)	int fd;	char **bpp;	int size;{	faio_t	*f;	int	len;again:	f = faio_ref(buf_idx);	if (f->owner == owner_faio) {		f->owner = owner_writer;		if (++buf_idx >= faio_buffers)			buf_idx = 0;		f = faio_ref(buf_idx);	}	if ((sp->puts - sp->gets) < sp->cont_low && sp->done == 0) {		EDEBUG(("gets: %d puts: %d cont: %d low: %d\n", sp->gets, sp->puts, sp->puts - sp->gets, sp->cont_low));		sp->cont_low = sp->puts - sp->gets;	}	faio_wait_on_buffer(f, owner_reader, READER_DELAY, READER_MAXWAIT);	len = f->len;		if (f->fd != fd) {		if (f->len == 0) {			/*			 * If the tracksize for this track was known, and			 * the tracksize is 0 mod bytespt, this happens.			 */			goto again;		}		comerrno(EX_BAD,		"faio_get_buf fatal: fd=%d, f->fd=%d, f->len=%d f->errno=%d\n",		fd, f->fd, f->len, f->saved_errno);	}	if (size < len) {		comerrno(EX_BAD,		"unexpected short read-attempt in faio_get_buf. size = %d, len = %d\n",		size, len);	}	if (len < 0)		errno = f->saved_errno;	sp->gets++;	*bpp = f->bufp;	f->owner = owner_faio;	return len;}EXPORT voidfifo_stats(){	errmsgno(EX_BAD, "fifo had %ld puts and %ld gets.\n",		sp->puts, sp->gets);	errmsgno(EX_BAD, "fifo was %ld times empty and %ld times full, min fill was %ld%%.\n",		sp->empty, sp->full, (100L*sp->cont_low)/faio_buffers);}EXPORT intfifo_percent(addone)	BOOL	addone;{	int	percent;	if (buflen == 0L)		return (-1);	if (sp->done)		return (100);	percent = (100*(sp->puts + 1 - sp->gets)/faio_buffers);	if (percent > 100)		return (100);	return (percent);}#else	/* FIFO */#include <standard.h>#include <sys/types.h>#include <utypes.h>#include "cdrecord.h"EXPORT	void	init_fifo	__PR((long));EXPORT	BOOL	init_faio	__PR((int tracks, track_t *track, int));EXPORT	BOOL	await_faio	__PR((void));EXPORT	void	kill_faio	__PR((void));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;{	errmsgno(EX_BAD, "Fifo not supported.\n");}EXPORT BOOLinit_faio(tracks, track, bufsize)	int	tracks;	track_t	*track;	int	bufsize;{	return (FALSE);}EXPORT BOOLawait_faio(){	return (TRUE);}EXPORT voidkill_faio(){}EXPORT intfaio_read_buf(fd, bp, size)	int fd;	char *bp;	int size;{	return (0);}EXPORT intfaio_get_buf(fd, bpp, size)	int fd;	char **bpp;	int size;{	return (0);}EXPORT voidfifo_stats(){}EXPORT intfifo_percent(addone)	BOOL	addone;{	return (-1);}#endif /* FIFO */

⌨️ 快捷键说明

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