?? daemon.c
字號(hào):
/* * This source code is a part of coLinux source package. * * Dan Aloni <da-x@colinux.org>, 2003 (c) * * The code is licensed under the GPL. See the COPYING file at * the root directory. * */ #include <colinux/common/common.h>#include <colinux/common/version.h>#include <colinux/common/libc.h>#include <colinux/os/user/file.h>#include <colinux/os/user/misc.h>#include <colinux/os/user/exec.h>#include <colinux/os/alloc.h>#include <colinux/os/timer.h>#include <colinux/user/macaddress.h>#include <colinux/user/debug.h>#include <memory.h>#include <stdarg.h>#include <stdlib.h>#include "daemon.h"#include "manager.h"#include "monitor.h"#include "config.h"#include "reactor.h"co_rc_t co_load_config_file(co_daemon_t *daemon){ co_rc_t rc; if (daemon->start_parameters->cmdline_config) { daemon->config = daemon->start_parameters->config; return CO_RC(OK); } co_terminal_print_color(CO_TERM_COLOR_YELLOW, "XML configuration files are obsolete. Please pass command line\n"); co_terminal_print_color(CO_TERM_COLOR_YELLOW, "options, or use '@' to pass a command-line compatible configuration\n"); co_terminal_print_color(CO_TERM_COLOR_YELLOW, "file (e.g. @config.txt)\n\n"); rc = CO_RC(ERROR); return rc;}void co_daemon_print_header(void){ static int printed_already = 0; if (printed_already) return; co_terminal_print("Cooperative Linux Daemon, " COLINUX_VERSION "\n"); co_terminal_print("Compiled on " __DATE__ " " __TIME__ "\n"); co_terminal_print("\n"); printed_already = 1;}void co_daemon_syntax(){ co_daemon_print_header(); co_terminal_print("syntax: \n"); co_terminal_print("\n"); co_terminal_print(" colinux-daemon [-d] [-h] [k] [-t name] [-v level] [configuration and boot parameter] @params.txt\n"); co_terminal_print("\n"); co_terminal_print(" -d Don't launch and attach a coLinux console on startup\n"); co_terminal_print(" -h Show this help text\n"); co_terminal_print(" -k Suppress kernel messages\n"); co_terminal_print(" -p pidfile Write pid to file.\n"); co_terminal_print(" -t name When spawning a console, this is the type of console\n"); co_terminal_print(" (e.g, nt, fltk, etc...)\n"); co_terminal_print(" -v level Verbose messages, level 1 prints booting details, 2 or\n"); co_terminal_print(" more checks configs, 3 prints errors, default is 0 (off)\n"); co_terminal_print(" @params.txt Take more command line params from the given text file\n"); co_terminal_print(" (can be multi-line)\n"); co_terminal_print("\n"); co_terminal_print("Configuration and boot parameters:\n"); co_terminal_print("\n"); co_terminal_print("Params should start with kernel=vmlinux (is the kernel image file\n"); co_terminal_print("the '@' option is not needed. Instead, you pass all configuration\n"); co_terminal_print("via the command line, for example:\n"); co_terminal_print("\n"); co_terminal_print(" colinux-daemon kernel=vmlinux cobd0=root_fs hda1=:cobd0 root=/dev/cobd0 eth0=slirp\n"); co_terminal_print(" \n"); co_terminal_print("\n"); co_terminal_print("Use of new aliases automatically allocates cobd(s), for example:\n"); co_terminal_print("\n"); co_terminal_print(" colinux-daemon mem=32 kernel=vmlinux hda1=root_fs root=/dev/hda1 \\\n"); co_terminal_print(" eth0=pcap-bridge,\"Local Area Connection\"\n"); co_terminal_print("\n"); co_terminal_print("Unhandled parameters are forwarded to the kernel's boot parameters string.\n"); co_terminal_print("See README.txt for more details about command-line usage.\n"); co_terminal_print("See colinux-daemon's documentation for more options.\n"); co_terminal_print("\n");}co_rc_t co_daemon_parse_args(co_command_line_params_t cmdline, co_start_parameters_t *start_parameters){ co_rc_t rc; bool_t dont_launch_console = PFALSE; bool_t verbose_specified = PFALSE; int verbose_level = 0; co_snprintf(start_parameters->console, sizeof(start_parameters->console), "fltk"); rc = co_cmdline_params_one_arugment_parameter(cmdline, "-c", &start_parameters->config_specified, start_parameters->config_path, sizeof(start_parameters->config_path)); if (!CO_OK(rc)) return rc; rc = co_cmdline_params_one_arugment_parameter(cmdline, "-p", &start_parameters->pidfile_specified, start_parameters->pidfile, sizeof(start_parameters->pidfile)); if (!CO_OK(rc)) return rc; rc = co_cmdline_params_one_arugment_parameter(cmdline, "-t", NULL, start_parameters->console, sizeof(start_parameters->console)); if (!CO_OK(rc)) return rc; rc = co_cmdline_params_argumentless_parameter(cmdline, "-d", &dont_launch_console); if (!CO_OK(rc)) return rc; rc = co_cmdline_params_argumentless_parameter(cmdline, "-k", &start_parameters->suppress_printk); if (!CO_OK(rc)) return rc; rc = co_cmdline_params_one_arugment_int_parameter(cmdline, "-v", &verbose_specified, &verbose_level); if (co_global_debug_levels.misc_level < verbose_level) co_global_debug_levels.misc_level = verbose_level; rc = co_cmdline_params_argumentless_parameter(cmdline, "-h", &start_parameters->show_help); if (!CO_OK(rc)) return rc; start_parameters->launch_console = !dont_launch_console; rc = co_parse_config_args(cmdline, start_parameters); if (!CO_OK(rc)) { co_terminal_print("daemon: error parsing configuration parameters and boot params\n"); return rc; } return CO_RC(OK);}static void init_srand(void){ co_timestamp_t t; co_os_get_timestamp(&t); srand(t.low ^ t.high);}co_rc_t co_daemon_create(co_start_parameters_t *start_parameters, co_daemon_t **co_daemon_out){ co_rc_t rc; co_daemon_t *daemon; init_srand(); daemon = co_os_malloc(sizeof(co_daemon_t)); if (daemon == NULL) { rc = CO_RC(OUT_OF_MEMORY); goto out; } memset(daemon, 0, sizeof(*daemon)); daemon->start_parameters = start_parameters; memcpy(daemon->config.config_path, start_parameters->config_path, sizeof(start_parameters->config_path)); rc = co_load_config_file(daemon); if (!CO_OK(rc)) { co_debug_error("error loading configuration"); goto out_free; } *co_daemon_out = daemon; return rc;out_free: co_os_free(daemon);out: return rc;}void co_daemon_destroy(co_daemon_t *daemon){ co_debug("daemon cleanup"); co_os_free(daemon);}/* Remember: Strip tool scans only this file for needed symbols */staticco_rc_t co_daemon_load_symbol_and_data(co_daemon_t *daemon, const char *symbol_name, unsigned long *address_out, void *buffer, unsigned long buffer_size){ co_rc_t rc = CO_RC_OK; co_elf_symbol_t *sym; void *data; sym = co_get_symbol_by_name(daemon->elf_data, symbol_name); if (sym) *address_out = co_elf_get_symbol_value(sym); else { co_debug_error("symbol %s not found", symbol_name); return CO_RC(ERROR); } data = co_elf_get_symbol_data(daemon->elf_data, sym); if (data == NULL) { co_debug_error("data of symbol %s not found", symbol_name); return CO_RC(ERROR); } memcpy(buffer, data, buffer_size); return rc;}/* Remember: Strip tool scans only this file for needed symbols */staticco_rc_t co_daemon_load_symbol(co_daemon_t *daemon, const char *symbol_name, unsigned long *address_out){ co_rc_t rc = CO_RC_OK; co_elf_symbol_t *sym; sym = co_get_symbol_by_name(daemon->elf_data, symbol_name); if (sym) *address_out = co_elf_get_symbol_value(sym); else { co_debug_error("symbol %s not found", symbol_name); rc = CO_RC(ERROR); } return rc;}void co_daemon_prepare_net_macs(co_daemon_t *daemon){ int i; for (i=0; i < CO_MODULE_MAX_CONET; i++) { co_netdev_desc_t *net_dev; net_dev = &daemon->config.net_devs[i]; if (net_dev->enabled == PFALSE) continue; if (net_dev->manual_mac_address == PFALSE) { unsigned long rand_mac = rand(); int i; for (i=0; i < 10; i++) rand_mac *= rand() + 1234; net_dev->mac_address[0] = 0; net_dev->mac_address[1] = 0xFF; net_dev->mac_address[2] = rand_mac >> 030; net_dev->mac_address[3] = rand_mac >> 020; net_dev->mac_address[4] = rand_mac >> 010; net_dev->mac_address[5] = rand_mac >> 000; } }}co_rc_t co_load_initrd(co_daemon_t *daemon){ co_rc_t rc; char *initrd; unsigned long initrd_size; if (!daemon->config.initrd_enabled) return CO_RC(OK); co_debug("reading initrd from (%s)", daemon->config.initrd_path); rc = co_os_file_load(daemon->config.initrd_path, &initrd, &initrd_size, 0); if (!CO_OK(rc)) { co_terminal_print("error loading initrd file\n"); return rc; } co_debug("initrd size: %ld bytes", initrd_size); rc = co_user_monitor_load_initrd(daemon->monitor, initrd, initrd_size); co_os_free(initrd); return rc;}static void memory_usage_limit_resached(co_manager_ioctl_create_t *create_params){ co_manager_ioctl_info_t info = {0, }; co_manager_handle_t handle; co_rc_t rc; co_terminal_print("colinux: memory size configuration for this VM: %ld MB\n", create_params->actual_memsize_used / 0x100000); co_terminal_print("colinux: memory usage limit reached\n"); co_terminal_print("colinux: try to decrease memory size configuration\n"); handle = co_os_manager_open(); if (!handle) { co_terminal_print("colinux: error opening manager\n"); return; } rc = co_manager_info(handle, &info); if (!CO_OK(rc)) { co_terminal_print("colinux: erroneous manager info\n"); co_os_manager_close(handle); return; } co_os_manager_close(handle); co_terminal_print("colinux: memory usage limit: %ld MB\n", info.hostmem_usage_limit / 0x100000); co_terminal_print("colinux: current memory used by running VMs: %ld MB\n", info.hostmem_used / 0x100000);}co_rc_t co_daemon_monitor_create(co_daemon_t *daemon){ co_manager_ioctl_create_t create_params = {0, }; co_symbols_import_t *import; co_rc_t rc; import = &create_params.import; rc = co_daemon_load_symbol(daemon, "_kernel_start", &import->kernel_start); if (!CO_OK(rc)) goto out; rc = co_daemon_load_symbol(daemon, "_end", &import->kernel_end); if (!CO_OK(rc)) goto out; rc = co_daemon_load_symbol(daemon, "init_thread_union", &import->kernel_init_task_union); if (!CO_OK(rc)) { goto out; } rc = co_daemon_load_symbol(daemon, "co_start", &import->kernel_colinux_start); if (!CO_OK(rc)) goto out; rc = co_daemon_load_symbol(daemon, "swapper_pg_dir", &import->kernel_swapper_pg_dir); if (!CO_OK(rc)) goto out; rc = co_daemon_load_symbol(daemon, "idt_table", &import->kernel_idt_table); if (!CO_OK(rc)) goto out; if (co_get_symbol_by_name(daemon->elf_data, "per_cpu__gdt_page")) // >= 2.6.22 rc = co_daemon_load_symbol(daemon, "per_cpu__gdt_page", &import->kernel_gdt_table); else // <= 2.6.17 rc = co_daemon_load_symbol(daemon, "cpu_gdt_table", &import->kernel_gdt_table); if (!CO_OK(rc)) goto out; rc = co_daemon_load_symbol_and_data(daemon, "co_info", &import->kernel_co_info, &create_params.info, sizeof(create_params.info)); if (!CO_OK(rc)) { goto out; } rc = co_daemon_load_symbol_and_data(daemon, "co_arch_info", &import->kernel_co_arch_info, &create_params.arch_info, sizeof(create_params.arch_info)); if (!CO_OK(rc)) { goto out; } if (create_params.info.api_version != CO_LINUX_API_VERSION) { co_terminal_print("colinux: error, expected kernel API version %d, got %ld\n", CO_LINUX_API_VERSION, create_params.info.api_version); rc = CO_RC(VERSION_MISMATCHED); goto out; } if (create_params.info.compiler_abi != __GXX_ABI_VERSION) { co_terminal_print("colinux: error, expected gcc abi version %d, got %ld\n", __GXX_ABI_VERSION, create_params.info.compiler_abi); co_terminal_print("colinux: Daemons gcc version %d.%d.x, " "incompatible to kernel gcc version %ld.%ld.x\n", __GNUC__, __GNUC_MINOR__, create_params.info.compiler_major, create_params.info.compiler_minor); rc = CO_RC(COMPILER_MISMATCHED); goto out; } co_daemon_prepare_net_macs(daemon); create_params.config = daemon->config; rc = co_user_monitor_create(&daemon->monitor, &create_params); if (!CO_OK(rc)) { if (CO_RC_GET_CODE(rc) == CO_RC_HOSTMEM_USE_LIMIT_REACHED) { memory_usage_limit_resached(&create_params); } goto out; } daemon->shared = (co_monitor_user_kernel_shared_t *)create_params.shared_user_address; if (!daemon->shared) return CO_RC(ERROR); daemon->shared->userspace_msgwait_count = 0; daemon->id = create_params.id; rc = co_load_initrd(daemon);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -