Пример #1
0
int main(int argc, char **argv)//内核发生热插拔时会执行一次/proc/sys/kernel/hotplug。
{///sbin/mdev > /proc/sys/kernel/hotplug,本质上内核发生一次热插拔时执行一次/sbin/mdev
	int ch;
	char *dbglvl = getenv("DBGLVL");

	if (dbglvl) {
		debug = atoi(dbglvl);
		unsetenv("DBGLVL");
	}

	while ((ch = getopt(argc, argv, "d:s:h:")) != -1) {
		switch (ch) {
		case 'h':
			return hotplug_run(optarg);//执行hotplug_run(/etc/hotplug-preinit.json):
		case 's':
			ubus_socket = optarg;
			break;
		case 'd':
			debug = atoi(optarg);
			break;
		default:
			return usage(argv[0]);
		}
	}
	uloop_init();
	procd_signal();
	trigger_init();
	if (getpid() != 1)
		procd_connect_ubus();
	else
		procd_state_next();//进程pid=1才执行procd_state_next,这才是开机启动流程中的procd,负责解析/etc/inittab文件并据此依次启动系统。
	uloop_run();

	return 0;
}
Пример #2
0
static void rcdone(struct runqueue *q)
{
	procd_state_next();
}
Пример #3
0
static void coldplug_complete(struct uloop_timeout *t)
{
	DEBUG(4, "Coldplug complete\n");
	hotplug_last_event(NULL);
	procd_state_next();
}
Пример #4
0
Файл: state.c Проект: asac/procd
static void set_console(void)
{
	const char* tty;
	char* split;
	char line[ 20 ];
	const char* try[] = { "tty0", "console", NULL }; /* Try the most common outputs */
	int f, i = 0;

	tty = get_cmdline_val("console",line,sizeof(line));
	if (tty != NULL) {
		split = strchr(tty, ',');
		if ( split != NULL )
			*split = '\0';
	} else {
		// Try a default
		tty=try[i];
		i++;
	}

	if (chdir("/dev")) {
		ERROR("failed to change dir to /dev\n");
		return;
	}
	while (tty!=NULL) {
		f = open(tty, O_RDONLY);
		if (f >= 0) {
			close(f);
			break;
		}

		tty=try[i];
		i++;
	}
	if (chdir("/"))
		ERROR("failed to change dir to /\n");

	if (tty != NULL)
		set_stdio(tty);
}

static void state_enter(void)
{
	char ubus_cmd[] = "/sbin/ubusd";

	switch (state) {
	case STATE_EARLY:
		LOG("- early -\n");
		watchdog_init(0);
		hotplug("/etc/hotplug.json");
		procd_coldplug();
		break;

	case STATE_UBUS:
		// try to reopen incase the wdt was not available before coldplug
		watchdog_init(0);
		set_stdio("console");
		LOG("- ubus -\n");
		procd_connect_ubus();
		service_start_early("ubus", ubus_cmd);
		break;

	case STATE_INIT:
		LOG("- init -\n");
		procd_inittab();
		procd_inittab_run("respawn");
		procd_inittab_run("askconsole");
		procd_inittab_run("askfirst");
		procd_inittab_run("sysinit");

		// switch to syslog log channel
		ulog_open(ULOG_SYSLOG, LOG_DAEMON, "procd");
		break;

	case STATE_RUNNING:
		LOG("- init complete -\n");
		break;

	case STATE_SHUTDOWN:
		/* Redirect output to the console for the users' benefit */
		set_console();
		LOG("- shutdown -\n");
		procd_inittab_run("shutdown");
		sync();
		break;

	case STATE_HALT:
		// To prevent killed processes from interrupting the sleep
		signal(SIGCHLD, SIG_IGN);
		LOG("- SIGTERM processes -\n");
		kill(-1, SIGTERM);
		sync();
		sleep(1);
		LOG("- SIGKILL processes -\n");
		kill(-1, SIGKILL);
		sync();
		sleep(1);
#ifndef DISABLE_INIT
		if (reboot_event == RB_POWER_OFF)
			LOG("- power down -\n");
		else
			LOG("- reboot -\n");

		/* Allow time for last message to reach serial console, etc */
		sleep(1);

		/* We have to fork here, since the kernel calls do_exit(EXIT_SUCCESS)
		 * in linux/kernel/sys.c, which can cause the machine to panic when
		 * the init process exits... */
		if (!vfork( )) { /* child */
			reboot(reboot_event);
			_exit(EXIT_SUCCESS);
		}
		while (1)
			sleep(1);
#else
		exit(0);
#endif
		break;

	default:
		ERROR("Unhandled state %d\n", state);
		return;
	};
}

void procd_state_next(void)
{
	DEBUG(4, "Change state %d -> %d\n", state, state + 1);
	state++;
	state_enter();
}

void procd_state_ubus_connect(void)
{
	if (state == STATE_UBUS)
		procd_state_next();
}

void procd_shutdown(int event)
{
	if (state >= STATE_SHUTDOWN)
		return;
	DEBUG(2, "Shutting down system with event %x\n", event);
	reboot_event = event;
	state = STATE_SHUTDOWN;
	state_enter();
}