Änderung an Linuxkonsolenprogramm



  • Guten Tag 🤡... Tut mir leid gleich mit dem ersten Post eine Frage stellen zu müssen, aber irgendwie muss jeder ja mal anfangen, oder =)?

    Also ich bin noch relativ unerfahren auf dem Gebiet der C++ Programmierung, vielleicht ändert sich das ja nun mit der Zeit :).

    Derzeit möchte ich für ein privates Projekt gerne das Linuxkonsolenprogramm PV (PipeViewer http://www.ivarch.com/programs/pv.shtml) umschreiben.

    Und zwar möchte ich das die Geschwindigkeit der Pipeausgabe je nach Geschwindigkeit eines Downloads von mehreren Datei angepasst wird.

    Also soweit bin ich bis jetzt gekommen:

    LOOP.C:

    /*
     * Main program entry point - read the command line options, then perform
     * the appropriate actions.
     *
     * Copyright 2008 Andrew Wood, distributed under the Artistic License 2.0.
     */
    
    #include "options.h"
    #include "pv.h"
    
    #define _GNU_SOURCE 1
    #include <limits.h>
    
    #include <unistd.h>
    #include <signal.h>
    #include <fcntl.h>
    #include <sys/ioctl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/time.h>
    
    #ifdef HAVE_CONFIG_H
    #include "config.h"
    #endif
    
    #define RATE_GRANULARITY	100000	    /* usec between -L rate chunks */
    
    extern struct timeval pv_sig_toffset;
    extern sig_atomic_t pv_sig_newsize;
    extern sig_atomic_t pv_sig_abort;
    
    /*
     * Add the given number of microseconds (which may be negative) to the given
     * timeval.
     */
    static void pv_timeval_add_usec(struct timeval *val, long usec)
    {
    	val->tv_usec += usec;
    	while (val->tv_usec < 0) {
    		val->tv_sec--;
    		val->tv_usec += 1000000;
    	}
    	while (val->tv_usec >= 1000000) {
    		val->tv_sec++;
    		val->tv_usec -= 1000000;
    	}
    }
    
    /*
     * Pipe data from a list of files to standard output, giving information
     * about the transfer on standard error according to the given options.
     *
     * Returns nonzero on error.
     */
    int pv_main_loop(opts_t opts)
    {
    	long written, lineswritten;
    	long long total_written, since_last, cansend, donealready, target;
    	int eof_in, eof_out, final_update;
    	struct timeval start_time, next_update, next_reset, cur_time;
    	struct timeval init_time;
    	long double elapsed;
    	struct stat64 sb;
    	int fd, n;
    
    	/*
    	 * "written" is ALWAYS bytes written by the last transfer.
    	 *
    	 * "lineswritten" is the lines written by the last transfer,
    	 * but is only updated in line mode.
    	 *
    	 * "total_written" is the total bytes written since the start,
    	 * or in line mode, the total lines written since the start.
    	 *
    	 * "since_last" is the bytes written since the last display,
    	 * or in line mode, the lines written since the last display.
    	 *
    	 * The remaining variables are all unchanged by linemode.
    	 */
    
    	fd = -1;
    
    	pv_crs_init(opts);
    
    	eof_in = 0;
    	eof_out = 0;
    	total_written = 0;
    	since_last = 0;
    
    	gettimeofday(&start_time, NULL);
    	gettimeofday(&cur_time, NULL);
    
    	next_update.tv_sec = start_time.tv_sec;
    	next_update.tv_usec = start_time.tv_usec;
    	pv_timeval_add_usec(&next_update,
    			    (long) (1000000.0 * opts->interval));
    
    	next_reset.tv_sec = start_time.tv_sec;
    	next_reset.tv_usec = start_time.tv_usec;
    	pv_timeval_add_usec(&next_reset, RATE_GRANULARITY);
    
    	cansend = 0;
    	donealready = 0;
    	final_update = 0;
    	n = 0;
    
    	fd = pv_next_file(opts, n, -1);
    	if (fd < 0) {
    		return 1;
    	}
    
    	if (fstat64(fd, &sb) == 0) {
    		pv_set_buffer_size(sb.st_blksize * 32, 0);
    	}
    
    	if (opts->buffer_size > 0) {
    		pv_set_buffer_size(opts->buffer_size, 1);
    	}
    
    	while ((!(eof_in && eof_out)) || (!final_update)) {
    
    		if (pv_sig_abort)
    			break;
    
    		if (opts->rate_limit > 0) {
    			target =
    			    ((long double) (opts->rate_limit)) /
    			    (long double) (1000000 / RATE_GRANULARITY);
    			cansend = target - donealready;
    			if (target < donealready)
    				cansend = 0;
    		}
    
    		written =
    		    pv_transfer(opts, fd, &eof_in, &eof_out, cansend,
    				&lineswritten);
    		if (written < 0)
    			return 1;
    
    		if (opts->linemode) {
    			since_last += lineswritten;
    			total_written += lineswritten;
    		} else {
    			since_last += written;
    			total_written += written;
    		}
    		if (opts->rate_limit > 0)
    			donealready += written;
    
    		if (eof_in && eof_out && n < (opts->argc - 1)) {
    			n++;
    			fd = pv_next_file(opts, n, fd);
    			if (fd < 0)
    				return 1;
    			eof_in = 0;
    			eof_out = 0;
    		}
    
    		gettimeofday(&cur_time, NULL);
    
    		if (eof_in && eof_out) {
    			final_update = 1;
    			next_update.tv_sec = cur_time.tv_sec - 1;
    		}
    
    		if ((cur_time.tv_sec > next_reset.tv_sec)
    		    || (cur_time.tv_sec == next_reset.tv_sec
    			&& cur_time.tv_usec >= next_reset.tv_usec)) {
    			pv_timeval_add_usec(&next_reset, RATE_GRANULARITY);
    			if (next_reset.tv_sec < cur_time.tv_sec)
    				next_reset.tv_sec = cur_time.tv_sec;
    			donealready = 0;
    		}
    
    		if (opts->no_op)
    			continue;
    
    		/*
    		 * If -W was given, we don't output anything until we have
    		 * written a byte (or line, in line mode), at which point
    		 * we then count time as if we started when the first byte
    		 * was received.
    		 */
    		if (opts->wait) {
    			if (opts->linemode) {
    				if (lineswritten < 1)
    					continue;
    			} else {
    				if (written < 1)
    					continue;
    			}
    
    			opts->wait = 0;
    
    			/*
    			 * Reset the timer offset counter now that data
    			 * transfer has begun, otherwise if we had been
    			 * stopped and started (with ^Z / SIGTSTOP)
    			 * previously (while waiting for data), the timers
    			 * will be wrongly offset.
    			 *
    			 * While we reset the offset counter we must disable
    			 * SIGTSTOP so things don't mess up.
    			 */
    			pv_sig_nopause();
    			gettimeofday(&start_time, NULL);
    			pv_sig_toffset.tv_sec = 0;
    			pv_sig_toffset.tv_usec = 0;
    			pv_sig_allowpause();
    
    			next_update.tv_sec = start_time.tv_sec;
    			next_update.tv_usec = start_time.tv_usec;
    			pv_timeval_add_usec(&next_update,
    					    (long) (1000000.0 *
    						    opts->interval));
    		}
    
    		if ((cur_time.tv_sec < next_update.tv_sec)
    		    || (cur_time.tv_sec == next_update.tv_sec
    			&& cur_time.tv_usec < next_update.tv_usec)) {
    			continue;
    		}
    
    		pv_timeval_add_usec(&next_update,
    				    (long) (1000000.0 * opts->interval));
    
    		if (next_update.tv_sec < cur_time.tv_sec) {
    			next_update.tv_sec = cur_time.tv_sec;
    			next_update.tv_usec = cur_time.tv_usec;
    		} else if (next_update.tv_sec == cur_time.tv_sec
    			   && next_update.tv_usec < cur_time.tv_usec) {
    			next_update.tv_usec = cur_time.tv_usec;
    		}
    
    		init_time.tv_sec =
    		    start_time.tv_sec + pv_sig_toffset.tv_sec;
    		init_time.tv_usec =
    		    start_time.tv_usec + pv_sig_toffset.tv_usec;
    		if (init_time.tv_usec >= 1000000) {
    			init_time.tv_sec++;
    			init_time.tv_usec -= 1000000;
    		}
    		if (init_time.tv_usec < 0) {
    			init_time.tv_sec--;
    			init_time.tv_usec += 1000000;
    		}
    
    		elapsed = cur_time.tv_sec - init_time.tv_sec;
    		elapsed +=
    		    (cur_time.tv_usec - init_time.tv_usec) / 1000000.0;
    
    		if (final_update)
    			since_last = -1;
    
    		if (pv_sig_newsize) {
    			pv_sig_newsize = 0;
    			pv_screensize(opts);
    		}
    
    		pv_display(opts, elapsed, since_last, total_written);
    
    		since_last = 0;
    	}
    
    	if (opts->cursor) {
    		pv_crs_fini(opts);
    	} else {
    		if ((!opts->numeric) && (!opts->no_op))
    			write(STDERR_FILENO, "\n", 1);
    	}
    
    	/*
    	 * Free up the buffers used by the display and data transfer
    	 * routines.
    	 */
    	pv_display(0, 0, 0, 0);
    	pv_transfer(0, -1, 0, 0, 0, NULL);
    
    	return 0;
    }
    

    Wenn ich die Variable target anpasse kann ich die Geschwindigkeit auf einen festen Wert setzen (als wenn ich das Programm mit --limit-rate aufrufe). Für meine beschränkten C++ Kenntnisse schon ein erheblicher Fortschritt :D.

    Nun würde ich ja gerne die Variable an die Geschwindigkeit eines Downloads (z.B. mit Wget) anpassen.
    Dafür müsste ich ja nur die Dateien in ein Verzeichnis runterladen und von diesem Verzeichnis in PV sekündlich die Größe ermitteln und vom vorherigen Wert abziehen, damit hätte ich die Geschwindkeit pro Sekunde.

    Nun macht sich aber schon meine nicht vorhandene Kenntniss bemerkbar. Zum debuggen würde ich z.B. gerne einige Sachen mit printf() ausgeben, aber egal wo ich ein printf("Test") hinsetze (+ ein #include <stdio.h> am Anfang), angezeigt wird beim Programmaufruf leider nichts (In der display.c hab ich es auch an diversen Stellen probiert, leider ohne Erfolg).

    Daher meine Fragen an diese Top Community hier:
    - Warum ist das so :)?
    - könnte ich in der Funktion "int pv_main_loop" denn überhaupt die Geschwindkeit ermitteln und dementsprechend die Variable target anpassen?
    -> Wenn ja könntet ihr mir einen Stups in die richtige richtung geben wie man sowas bewerkstelligen könnte
    -> Wenn nein könntet ihr mir einen Stups in die richtige richtung geben wie man sowas sonst bewerkstelligen könnte 😃

    Bin für jede noch so kleine Hilfe sehr sehr dankbar und versuche mich künftig in diesem klasse Forum konstruktiv zu beteiligen 🤡...



  • Auch wenn du noch öfter das Klasse Forum unterstreichst, wird dir bei deinem Problem so schnell niemand helfen. Das kommt immer wieder vor, dass jemand ein existierendes Programm hat und da selber etwas ändern will/muss, aber keinen Peil hat und deshalb hier um Hilfe bittet. Die Antwort lautet dann meist "Lern selber Programmieren".
    Mit ein wenig experimentieren wirst du nicht weit kommen, wenn du nicht weißt was du gerade verändert hast. Im Endeffekt suchst du jemanden, der dir deine Wünsche in das Programm einpflegt - wenn das jemand macht dann wohl nur gegen Bares 😕

    BTW.: Das hier ist das C++-Forum, der Code aber nur reinstes C, dafür gibt es ein eigenes Unterforum. Aber ich denke auch da wird dir niemand deinen Code 4free anpassen...



  • Dieser Thread wurde von Moderator/in pumuckl aus dem Forum C++ in das Forum ANSI C verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.


Log in to reply