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

📄 dtprocs.c

📁 Linux磁盘测试的源代码,测试磁盘的读写性能
💻 C
字号:
/**************************************************************************** *									    * *			  COPYRIGHT (c) 1990 - 2004			    * *			   This Software Provided			    * *				     By					    * *			  Robin's Nest Software Inc.			    * *									    * * Permission to use, copy, modify, distribute and sell this software and   * * its documentation for any purpose and without fee is hereby granted,	    * * provided that the above copyright notice appear in all copies and that   * * both that copyright notice and this permission notice appear in the	    * * supporting documentation, and that the name of the author not be used    * * in advertising or publicity pertaining to distribution of the software   * * without specific, written prior permission.				    * *									    * * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 	    * * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN	    * * NO EVENT SHALL HE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL   * * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR    * * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS  * * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF   * * THIS SOFTWARE.							    * *									    * ****************************************************************************//* * Module:	dtprocs.c * Author:	Robin T. Miller * Date:	August 7, 1993 * * Description: *	Functions to handle multiple processes for 'dt' program. * * Modification History: * * November 17th, 2003 by Robin Miller. *	Breakup output to stdout or stderr, rather than writing * all output to stderr.  If output file is stdout ('-') or a log * file is specified, then all output reverts to stderr. * * March 14th, 2003 by Robin Miller. *	Added support for testing an individual slice. * * May 31st, 2001 by Robin Miller. *	Update abort_procs() to use max_procs, valid for both multiple * processes and slices, and loop through entire process table since * some processes may have finished already (use to break out early). *	When starting slices with multiple processes, prime the data * pattern to ensure each process uses the same pattern in a slice. * * February 6th, 2001 by Robin Miller. *	If doing multiple slices in reverse direction, ensure the data * limit gets tot he slice length, or we'll overflow into previous slice. * * February 1st, 2001 by Robin Miller. *	Fix dumb problem starting multiple procs with multiple slices. * * January 28th, 2001 by Robin Miller. *	When aborting processes, send SIGINT instead of SIGTERM, so * statistics gets reported (important on long running commands :-). *	Added support for multiple slices option.  This sets up each * process exercising a different range of blocks (slice) on the disk. * * January 2nd, 2001 by Robin Miller. *      Make changes to build using MKS/NuTCracker product. * * March 28th, 2000 by Robin Miller. *	When creating multiple processes, do a better job determining * when a unique device name should be constructed.  Was broken for * named piped (FIFO's). * * May 3, 1999 by Robin Miller. *	Allocate more space for unique file names, since the size * of pid_t is now 31 bits in Steel. * * April 8, 1999 by Robin Miller. *	Merge in Jeff Detjen's changes for current process count. * * April 29, 1998 by Robin Miller. *	Add support for an alternate device directory. * * July 17, 1995 by Robin Miller. *	Apply a severity priority to child exit status. *	Added flag to ensure process abortion occurs only once. * * July 5, 1995 by Robin Miller. *	Properly check for child process exiting as result of a signal. * * March 28, 1995 by Robin Miller. *	Report specific error for "no processes started", and exit with *	error status if the system process limit has been exceeded. * * November 4, 1994 by Robin Miller. *	Don't set SIGCHLD signal to SIG_IGN (set to SIG_DFL) or else *	waitpid() won't detect any child processes (OSF R1.3 and QNX). *	[ Unfortunately, the POSIX standard states "The specification *	  of the effects of SIG_IGN on SIGCHLD as implementation defined *	  and permits, but does NOT require, the System V effect of *	  causing terminating children to be ignored by wait(). Yuck!!! ] */#include "dt.h"#include <signal.h>#include <sys/stat.h>#include <sys/wait.h>#define PROC_ALLOC (sizeof(pid_t) * 3)	/* Extra allocation for PID.	*//* * Structure to track multiple processes. */struct dt_procs {	pid_t	dt_pid;			/* The child process ID.	*/	int	dt_status;		/* The child exit status.	*/	bool	dt_active;		/* The process active flag.	*/};/* * Slice Range Definition: */typedef struct slice_info {	int	slice;			/* Slice number.		*/	large_t	slice_position;		/* Starting slice position.	*/	large_t	slice_length;		/* The slice data length.	*/} slice_info_t;/* * Forward References: */static void init_slice_info(struct dinfo *dip, slice_info_t *sip, large_t *data_resid);static void setup_slice(struct dinfo *dip, slice_info_t *sip);struct dt_procs *ptable;		/* Multiple 'dt' procs table.	*/int num_procs = 0;			/* Number of procs to create.	*/int cur_proc = 0;			/* Current count of processes.	*/int max_procs = 0;			/* Maximum processes started.	*/int procs_active = 0;			/* Number of active processes.	*/int num_slices = 0;			/* Number of slices to create.	*/int slice_num = 0;			/* Slice number to operate on.	*//* * abort_procs - Abort processes started by the parent. */voidabort_procs(void){    static int aborted_processes = FALSE;    struct dt_procs *dtp;    int procs;    pid_t pid;    if ((ptable == NULL) || aborted_processes)  return;    /*     * Force all processes to terminate.     */    for (dtp = ptable, procs=0; procs < max_procs; procs++, dtp++) {	if ((pid = dtp->dt_pid) == (pid_t) 0) continue;	if (debug_flag) {	    Printf("Aborting child process %d via a SIGINT (%d)...\n",								pid, SIGINT);	}	if (dtp->dt_active) (void) kill (pid, SIGINT);    }    aborted_processes = TRUE;}voidawait_procs(void){    pid_t wpid;    struct dt_procs *dtp;    int procs, status;    if (debug_flag) {	Printf ("Waiting for %d child processes to complete...\n", procs_active);    }    while (1) {	if ((wpid = waitpid ((pid_t) -1, &child_status, 0)) == FAILURE) {	    if (errno == ECHILD) {		if (procs_active) abort();	/* Programming error... */		break;				/* No more children... */	    } else if (errno == EINTR) {		abort_procs();		continue;	    } else {		report_error ("waitpid", FALSE);		exit (FATAL_ERROR);	    }	}	/*	 * Examine the child process status.	 */	if ( WIFSTOPPED(child_status) ) {	    Printf ("Child process %d, stopped by signal %d.\n",					wpid, WSTOPSIG(child_status));	    continue; /* Maybe attached from debugger... */	} else if ( WIFSIGNALED(child_status) ) {	    status = WTERMSIG(child_status);	    Fprintf ("Child process %d, exiting because of signal %d\n",							wpid, status);	} else { /* Process must be exiting... */	    status = WEXITSTATUS (child_status);	    if (debug_flag) {		Printf ("Child process %d, exiting with status %d\n",							wpid, status);	    }	}	if ( (exit_status == SUCCESS) && (status != SUCCESS) ) {	    if ( (oncerr_action == ABORT) &&		 (status != WARNING) && (status != END_OF_FILE) ) {		abort_procs();		/* Abort procs on error. */	    }	    /*	     * Save the most sever error for parent exit status.	     *	     * Severity Priorities:	WARNING		(lowest)	     *				END_OF_FILE	     *				Signal Number	     *				FATAL_ERROR	(highest)	     */	    if ( ((exit_status == SUCCESS) || (status == FATAL_ERROR)) ||		 ((exit_status == WARNING) && (status > WARNING))      ||		 ((exit_status == END_OF_FILE) && (status > WARNING)) ) {		exit_status = status;	/* Set error code for exit. */	    }	}	/*	 * House keeping... (mostly sanity check, not really necessary).	 */	for (dtp = ptable, procs = 0; procs < max_procs; procs++, dtp++) {	    if (dtp->dt_pid == wpid) {		dtp->dt_active = FALSE;		dtp->dt_status = status;		procs_active--;	    }	}    } /* End of while(1)... */}pid_tfork_process(void){    pid_t pid;    if ((pid = fork()) == (pid_t) -1) {	if (errno == EAGAIN) {	    if (procs_active == 0) {		LogMsg (efp, logLevelCrit, 0,	"ERROR: could NOT start any processes, please check your system...\n");		exit (FATAL_ERROR);	    } else {		Printf (	"WARNING: system imposed process limit reached, only %d procs started...\n",								procs_active);	    }	} else {	    report_error ("fork", FALSE);	    abort_procs();	}    }    return (pid);}pid_tstart_procs(void){    struct dt_procs *dtp;    size_t psize;    int procs;    max_procs = num_procs;    psize = (max_procs * sizeof(*dtp));    if ((ptable = (struct dt_procs *)malloc(psize)) == NULL) {	report_error ("No memory for proc table", FALSE);	exit (FATAL_ERROR);    }    bzero((char *)ptable, psize);#if !defined(__MSDOS__) || defined(__NUTC__)    (void) signal (SIGCHLD, SIG_DFL);#endif    (void) signal (SIGHUP, terminate);    (void) signal (SIGINT, terminate);    (void) signal (SIGTERM, terminate);    cur_proc = 1;    procs_active = 0;    for (dtp = ptable, procs = 0; procs < max_procs; procs++, dtp++) {	if ((child_pid = fork_process()) == (pid_t) -1) {	    break;	} else if (child_pid) {		/* Parent process gets the PID. */	    cur_proc++;	    dtp->dt_pid = child_pid;	    dtp->dt_active = TRUE;	    procs_active++;	    if (debug_flag) {		Printf ("Started Process %d...\n", child_pid);	    }	} else {			/* Child process... */	    struct stat sb;	    bool make_unique = FALSE;	    int error;	    if (!output_file) break;	    error = stat (output_file, &sb);	    if (!error) {		if ( S_ISREG(sb.st_mode) ) {		    make_unique = TRUE;		}	    /* Leave all other types alone! */	    } else if ( (NEL (output_file, DEV_PREFIX, DEV_LEN)) &&			(NEL (output_file, ADEV_PREFIX, ADEV_LEN)) ) {		make_unique = TRUE;	/* Ok, not a device directory. */	    }	    /*	     * Construct unique file name for file system I/O.	     */	    if (make_unique) {		char *bp;		bp = (char *)malloc(strlen(output_file) + PROC_ALLOC);		(void)sprintf(bp, "%s-%d", output_file, getpid());		output_dinfo->di_dname = output_file = bp;	    }	    break;			/* Child process, continue... */	}    }    return (child_pid);}pid_tstart_slices(void){    struct dinfo *dip = active_dinfo;    struct dt_procs *dtp;    size_t psize;    struct slice_info slice_info;    slice_info_t *sip = &slice_info;    large_t data_resid;    int procs;    max_procs = num_slices;    psize = (max_procs * sizeof(*dtp));    if ((ptable = (struct dt_procs *)malloc(psize)) == NULL) {	report_error ("No memory for proc table", FALSE);	exit (FATAL_ERROR);    }    bzero((char *)ptable, psize);#if !defined(__MSDOS__) || defined(__NUTC__)    (void) signal (SIGCHLD, SIG_DFL);#endif    (void) signal (SIGHUP, terminate);    (void) signal (SIGINT, terminate);    (void) signal (SIGTERM, terminate);    init_slice_info(dip, sip, &data_resid);    cur_proc = 1;    procs_active = 0;    for (dtp = ptable, procs = 0; procs < max_procs; procs++, dtp++) {	sip->slice++;	if ((child_pid = fork_process()) == (pid_t) -1) {	    break;	} else if (child_pid) {		/* Parent process gets the PID. */	    cur_proc++;	    dtp->dt_pid = child_pid;	    dtp->dt_active = TRUE;	    procs_active++;	    if (debug_flag) {		Printf ("Started Slice %d, PID %d...\n", sip->slice, child_pid);	    }	    if (procs < max_procs) {		sip->slice_position += sip->slice_length;		if (procs == max_procs) {		    sip->slice_length += data_resid;		}	    }	} else {			/* Child process... */	    /*	     * Initialize the starting data pattern for each slice.	     */	    if (unique_pattern) {		pattern = data_patterns[(cur_proc - 1) % npatterns];	    }	    setup_slice(dip, sip);	    break;			/* Child process, continue... */	}    }    return (child_pid);}voidinit_slice(struct dinfo *dip, int slice){    struct slice_info slice_info;    slice_info_t *sip = &slice_info;    large_t data_resid;    init_slice_info(dip, sip, &data_resid);    sip->slice_position += (sip->slice_length * (slice - 1));    /*     * Any residual goes to the last slice.     */    if (slice == num_slices) {	sip->slice_length += data_resid;    }    sip->slice = slice;    setup_slice(dip, sip);    /*     * Initialize the starting data pattern for each slice.     */    if (unique_pattern) {	pattern = data_patterns[(slice - 1) % npatterns];    }    return;}static voidinit_slice_info(struct dinfo *dip, slice_info_t *sip, large_t *data_resid){    large_t slice_length;    sip->slice = 0;    sip->slice_position = file_position;    slice_length = ((dip->di_data_limit - file_position) / num_slices);    sip->slice_length = rounddown(slice_length, dip->di_dsize);    if (sip->slice_length < dip->di_dsize) {	LogMsg (efp, logLevelCrit, 0,		"Slice length of " LUF " bytes is too small!\n",						sip->slice_length);	exit (FATAL_ERROR);    }    *data_resid = (dip->di_data_limit - (sip->slice_length * num_slices));    *data_resid = rounddown(*data_resid, dip->di_dsize);    return;}static voidsetup_slice(struct dinfo *dip, slice_info_t *sip){    file_position = sip->slice_position;    if (dip->di_random_io) {	rdata_limit = (file_position + sip->slice_length);    }    /*     * Restrict data limit to slice length or user set limit.     */    data_limit = MIN(data_limit, sip->slice_length);    if (debug_flag || Debug_flag) {	large_t dlimit = (dip->di_random_io) ? rdata_limit : data_limit;	Printf("Slice %d Information:\n"		"\t\t Start: " FUF " offset (lba %u)\n"		"\t\t   End: " FUF " offset (lba %u)\n"		"\t\tLength: " FUF " bytes (%d blocks)\n"		"\t\t Limit: " FUF " bytes (%d blocks)\n",		sip->slice,		file_position, (u_int32)(file_position / dip->di_dsize),		(file_position + sip->slice_length),		((file_position + sip->slice_length) / dip->di_dsize),		sip->slice_length, (sip->slice_length / dip->di_dsize),		dlimit, (dlimit / dip->di_dsize));    }    return;}

⌨️ 快捷键说明

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