예제 #1
0
파일: collector.c 프로젝트: sesam/bootchart
int main (int argc, char *argv[])
{
	Arguments args;
	int i, use_taskstat;
	int in_initrd, clean_environment = 1;
	int stat_fd, disk_fd, uptime_fd, meminfo_fd,  pid, ret = 1;
	PidScanner *scanner = NULL;
	unsigned long reltime = 0;
	BufferFile *stat_file, *disk_file, *per_pid_file, *meminfo_file;
	PidEventClosure pid_ev_cl;
	int *fds[] = { &stat_fd, &disk_fd, &uptime_fd, &meminfo_fd, NULL };
	const char *fd_names[] = { "/stat", "/diskstats", "/uptime", "/meminfo", NULL };
	StackMap map = STACK_MAP_INIT; /* make me findable */

	arguments_set_defaults (&args);
	arguments_parse (&args, argc, argv);

	if (args.usleep_time > 0) {
		usleep (args.usleep_time);
		return 0;
	}

	if (enter_environment (args.console_debug))
		return 1;

	fprintf (stderr, "bootchart-collector started as pid %d with %d args: ",
		 (int) getpid(), argc - 1);
	for (i = 1; i < argc; i++)
		fprintf (stderr, "'%s' ", argv[i]);
	fprintf (stderr, "\n");

	if (args.dump_path) {
		Arguments remote_args;

		ret = buffers_extract_and_dump (args.dump_path, &remote_args);
		ret |= dump_header (args.dump_path);

		if (!remote_args.relative_time)
			ret |= dump_dmsg (args.dump_path);
		if (!ret)
			cleanup_dev ();
		goto exit;
	}

	if (!args.relative_time) { /* manually started */
		in_initrd = am_in_initrd ();
		if (in_initrd && sanity_check_initrd ())
			goto exit;
	}

	pid = bootchart_find_running_pid (NULL);
	if (args.probe_running) {
		clean_environment = pid < 0;
		ret = pid < 0;
		goto exit;
	} else {
		if (pid >= 0) {
			clean_environment = 0;
			fprintf (stderr, "bootchart collector already running as pid %d, exiting...\n", pid);
			goto exit;
		}
	}
      
	/* defaults */
	if (!args.hz)
		args.hz = 50;

	for (i = 0; fds [i]; i++) {
		char *path = malloc (strlen (PROC_PATH) + strlen (fd_names[i]) + 1);
		strcpy (path, PROC_PATH);
		strcat (path, fd_names[i]);

		*fds[i] = open (path, O_RDONLY);
		if (*fds[i] < 0) {
			fprintf (stderr, "error opening '%s': %s'\n",
				 path, strerror (errno));
			exit (1);
		}
	}

	stat_file = buffer_file_new (&map, "proc_stat.log");
	disk_file = buffer_file_new (&map, "proc_diskstats.log");
	if ( (use_taskstat = init_taskstat()) )
		per_pid_file = buffer_file_new (&map, "taskstats.log");
	else
		per_pid_file = buffer_file_new (&map, "proc_ps.log");
	meminfo_file = buffer_file_new (&map, "proc_meminfo.log");
	pid_ev_cl.cmdline_file = buffer_file_new (&map, "cmdline2.log");
	pid_ev_cl.paternity_file = buffer_file_new (&map, "paternity.log");

	if (!stat_file || !disk_file || !per_pid_file || !meminfo_file ||
	    !pid_ev_cl.cmdline_file || !pid_ev_cl.paternity_file) {
		fprintf (stderr, "Error allocating output buffers\n");
		return 1;
	}

	scanner = pid_scanner_new_netlink (pid_event_cb, &pid_ev_cl);
	if (!scanner)
		scanner = pid_scanner_new_proc (PROC_PATH, pid_event_cb, &pid_ev_cl);
	if (!scanner)
		return 1;

	if (args.relative_time) {
		reltime = get_uptime (uptime_fd);
		if (! reltime)
			exit (1);
	}

	while (1) {
		pid_t pid;
		char uptime[80];
		size_t uptimelen;
		unsigned long u;

		if (in_initrd) {
			if (have_dev_tmpfs ()) {
				if (chroot_into_dev ()) {
					fprintf (stderr, "failed to chroot into /dev - exiting so run_init can proceed\n");
					return 1;
				}
				in_initrd = 0;
			}
		}
      
		u = get_uptime (uptime_fd);
		if (!u)
			return 1;

		uptimelen = sprintf (uptime, "%lu\n", u - reltime);

		buffer_file_dump_frame_with_timestamp (stat_file, stat_fd, uptime, uptimelen);
		buffer_file_dump_frame_with_timestamp (disk_file, disk_fd, uptime, uptimelen);
		buffer_file_dump_frame_with_timestamp (meminfo_file, meminfo_fd, uptime, uptimelen);

		/* output data for each pid */
		buffer_file_append (per_pid_file, uptime, uptimelen);

		pid_scanner_restart (scanner);
		while ((pid = pid_scanner_next (scanner))) {

			if (use_taskstat)
				dump_taskstat (per_pid_file, scanner);
			else
				dump_proc_stat (per_pid_file, pid);
		}
		buffer_file_append (per_pid_file, "\n", 1);

		usleep (1000000 / args.hz);
	}

	/*
	 * In reality - we are always killed before we reach
	 * this point
	 */
	if (use_taskstat) {
		if (close (netlink_socket) < 0) {
			perror ("failed to close netlink socket");
			exit (1);
		}
	}

	for (i = 0; fds [i]; i++) {
		if (close (*fds[i]) < 0) {
			fprintf (stderr, "error closing file '%s': %s'\n",
				 fd_names[i], strerror (errno));
			return 1;
		}
	}

	ret = 0;

 exit:
	arguments_free (&args);

	if (scanner)
		ret |= pid_scanner_free (scanner);

	if (clean_environment)
		clean_enviroment();

	return ret;
}
예제 #2
0
파일: dump.c 프로젝트: IngenicC/bootchart
/*
 * finds (another) bootchart-collector process and
 * returns it's pid (or -1) if not found, ignores
 * the --usleep mode we use to simplify our scripts.
 */
int
bootchart_find_running_pid (Arguments *opt_args)
{
	DIR *proc;
	struct dirent *ent;
	int pid = -1;
	char exe_path[1024];
	Arguments sargs, *args;

	if (opt_args) {
		args = opt_args;
	} else {
		args = &sargs;
		arguments_set_defaults (args);
	}
    
	proc = opendir (PROC_PATH);
	while ((ent = readdir (proc)) != NULL) {
		int len;
		char link_target[1024];

		if (!isdigit (ent->d_name[0]))
			continue;

		strcpy (exe_path, PROC_PATH);
		strcat (exe_path, "/");
		strcat (exe_path, ent->d_name);
		strcat (exe_path, "/exe");

		if ((len = readlink (exe_path, link_target, 1024-1)) < 0)
			continue;
		link_target[len] = '\0';

		if (strstr (link_target, PROGRAM_PREFIX "bootchart" PROGRAM_SUFFIX "-collector")) {
			FILE *argf;
			int harmless = 0;

			int p = atoi (ent->d_name);

			/*      log ("found collector '%s' pid %d (my pid %d)\n", link_target, p, getpid()); */

			if (p == getpid())
				continue; /* I'm not novel */

			strcpy (exe_path + strlen (exe_path) - strlen ("/exe"), "/cmdline");
			argf = fopen (exe_path, "r");
			if (argf) {
				int i;
				char abuffer[4096];

				len = fread (abuffer, 1, 4095, argf);
				if (len > 0) {
					/* step through args */
					int argc;
					char *argv[128];
					abuffer[len] = '\0';
					argv[0] = abuffer;
					for (argc = i = 0; i < len && argc < 127; i++) {
						if (abuffer[i] == '\0')
							argv[++argc] = abuffer + i + 1;
					}
					arguments_set_defaults (args);
					arguments_parse (args, argc, argv);

					if (args->usleep_time)
						harmless = 1;

				}
				fclose (argf);
			}

			if (!harmless) {
				pid = p;
				break;
			}
		}
	}
	closedir (proc);

	if (args == &sargs)
		arguments_free (&sargs);

	return pid;
}