From 3ce8a50bba8ba2918ec80ed4e57be23005024d78 Mon Sep 17 00:00:00 2001 From: Guowei Li <15035660024@163.com> Date: Fri, 23 Jan 2026 09:41:32 +0800 Subject: [PATCH 1/4] refactor(log): simplify logging mechanism and remove unused callbacks This commit refactors the logging system by removing the callback mechanism and direct file logging. The logging function now primarily outputs to syslog, streamlining the logging process. Additionally, the log_event structure and related functions have been eliminated to reduce complexity. BREAKING CHANGE: The log_log function signature has changed; it no longer includes the 'with_enter' parameter. --- tools/include/log.h | 35 ++-------- tools/log.c | 144 +++++------------------------------------ tools/virtio.c | 3 - tools/virtio_console.c | 26 -------- 4 files changed, 22 insertions(+), 186 deletions(-) diff --git a/tools/include/log.h b/tools/include/log.h index 268d983..4537e4b 100644 --- a/tools/include/log.h +++ b/tools/include/log.h @@ -20,44 +20,23 @@ #include #include -#include -#include #define LOG_VERSION "0.1.0" -typedef struct { - va_list ap; - const char *fmt; - const char *file; - struct tm *time; - void *udata; - int line; - int level; -} log_Event; - -typedef void (*log_LogFn)(log_Event *ev); -typedef void (*log_LockFn)(bool lock, void *udata); - enum { LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL }; -#define log_trace(...) log_log(1, LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__) -#define log_debug(...) log_log(1, LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__) -#define log_info(...) log_log(1, LOG_INFO, __FILE__, __LINE__, __VA_ARGS__) -#define log_warn(...) log_log(1, LOG_WARN, __FILE__, __LINE__, __VA_ARGS__) -#define log_error(...) log_log(1, LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__) -#define log_fatal(...) log_log(1, LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__) -// log_printf can be used like printf -#define log_printf(...) log_log(0, LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__) +#define log_trace(...) log_log(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__) +#define log_debug(...) log_log(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__) +#define log_info(...) log_log(LOG_INFO, __FILE__, __LINE__, __VA_ARGS__) +#define log_warn(...) log_log(LOG_WARN, __FILE__, __LINE__, __VA_ARGS__) +#define log_error(...) log_log(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__) +#define log_fatal(...) log_log(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__) const char *log_level_string(int level); -void log_set_lock(log_LockFn fn, void *udata); void log_set_level(int level); void log_set_quiet(bool enable); -int log_add_callback(log_LogFn fn, void *udata, int level); -int log_add_fp(FILE *fp, int level); -void log_log(int with_enter, int level, const char *file, int line, - const char *fmt, ...); +void log_log(int level, const char *file, int line, const char *fmt, ...); void multithread_log_init(); void mutithread_log_exit(); #endif diff --git a/tools/log.c b/tools/log.c index 7692cc3..0d0ab0e 100644 --- a/tools/log.c +++ b/tools/log.c @@ -32,157 +32,43 @@ #include "log.h" #include - -#define MAX_CALLBACKS 32 - -typedef struct { - log_LogFn fn; - void *udata; - int level; -} Callback; +#include +#include +#include static struct { - void *udata; - log_LockFn lock; int level; bool quiet; - Callback callbacks[MAX_CALLBACKS]; } L; static const char *level_strings[] = {"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"}; -#ifdef LOG_USE_COLOR -static const char *level_colors[] = {"\x1b[94m", "\x1b[36m", "\x1b[32m", - "\x1b[33m", "\x1b[31m", "\x1b[35m"}; -#endif - -static void stdout_callback(log_Event *ev, int with_enter) { - char buf[16]; - // put ev->time as a string into buf - buf[strftime(buf, sizeof(buf), "%H:%M:%S", ev->time)] = '\0'; - - if (with_enter) { -#ifdef LOG_USE_COLOR - fprintf(ev->udata, "%s %s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ", buf, - level_colors[ev->level], level_strings[ev->level], ev->file, - ev->line); -#else - fprintf(ev->udata, "%s %-5s %s:%d: ", buf, level_strings[ev->level], - ev->file, ev->line); -#endif - } - - vfprintf(ev->udata, ev->fmt, ev->ap); - if (with_enter) - fprintf(ev->udata, "\n"); - fflush(ev->udata); -} - -static void file_callback(log_Event *ev) { - char buf[64]; - buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ev->time)] = '\0'; - fprintf(ev->udata, "%s %-5s %s:%d: ", buf, level_strings[ev->level], - ev->file, ev->line); - vfprintf(ev->udata, ev->fmt, ev->ap); - fprintf(ev->udata, "\n"); - fflush(ev->udata); -} - -static void lock(void) { - if (L.lock) { - L.lock(true, L.udata); - } -} - -static void unlock(void) { - if (L.lock) { - L.lock(false, L.udata); - } -} +static const int syslog_levels[] = {LOG_DEBUG, LOG_DEBUG, LOG_INFO, + LOG_WARNING, LOG_ERR, LOG_CRIT}; const char *log_level_string(int level) { return level_strings[level]; } -void log_set_lock(log_LockFn fn, void *udata) { - L.lock = fn; - L.udata = udata; -} - void log_set_level(int level) { L.level = level; } void log_set_quiet(bool enable) { L.quiet = enable; } -int log_add_callback(log_LogFn fn, void *udata, int level) { - for (int i = 0; i < MAX_CALLBACKS; i++) { - if (!L.callbacks[i].fn) { - L.callbacks[i] = (Callback){fn, udata, level}; - return 0; - } - } - return -1; -} - -int log_add_fp(FILE *fp, int level) { - return log_add_callback(file_callback, fp, level); -} - -static void init_event(log_Event *ev, void *udata) { - if (!ev->time) { - time_t t = time(NULL); - ev->time = localtime(&t); - } - ev->udata = udata; -} - -void log_log(int with_enter, int level, const char *file, int line, - const char *fmt, ...) { +void log_log(int level, const char *file, int line, const char *fmt, ...) { if (L.quiet || level < L.level) { return; } - log_Event ev = { - .fmt = fmt, - .file = file, - .line = line, - .level = level, - }; - - lock(); - - if (!L.quiet && level >= L.level) { - init_event(&ev, stderr); - va_start(ev.ap, fmt); - stdout_callback(&ev, with_enter); - va_end(ev.ap); - } - - for (int i = 0; i < MAX_CALLBACKS && L.callbacks[i].fn; i++) { - Callback *cb = &L.callbacks[i]; - if (level >= cb->level) { - init_event(&ev, cb->udata); - va_start(ev.ap, fmt); - cb->fn(&ev); - va_end(ev.ap); - } - } - - unlock(); + /* Primary output to syslog */ + va_list ap; + va_start(ap, fmt); + char buf[2048]; + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + syslog(syslog_levels[level], "%s:%d: %s", file, line, buf); } -pthread_mutex_t MUTEX_LOG; -void log_lock(bool lock, void *udata); - void multithread_log_init() { - pthread_mutex_init(&MUTEX_LOG, NULL); - log_set_lock(log_lock, &MUTEX_LOG); + openlog("hvisor-tool", LOG_PID | LOG_NDELAY, LOG_DAEMON); } -void mutithread_log_exit() { pthread_mutex_destroy(&MUTEX_LOG); } - -void log_lock(bool lock, void *udata) { - pthread_mutex_t *LOCK = (pthread_mutex_t *)(udata); - if (lock) - pthread_mutex_lock(LOCK); - else - pthread_mutex_unlock(LOCK); -} \ No newline at end of file +void mutithread_log_exit() { closelog(); } \ No newline at end of file diff --git a/tools/virtio.c b/tools/virtio.c index 1f6dffb..335934b 100644 --- a/tools/virtio.c +++ b/tools/virtio.c @@ -1080,9 +1080,6 @@ void initialize_log() { log_level = LOG_WARN; #endif log_set_level(log_level); - - FILE *log_file = fopen("log.txt", "w+"); - log_add_fp(log_file, LOG_WARN); } int virtio_init() { diff --git a/tools/virtio_console.c b/tools/virtio_console.c index 14d8a21..084b7fb 100644 --- a/tools/virtio_console.c +++ b/tools/virtio_console.c @@ -68,12 +68,6 @@ static void virtio_console_event_handler(int fd, int epoll_type, void *param) { break; } len = readv(dev->master_fd, iov, n); - if (len > 0) { - for (int i = 0; i < len; i++) { - log_printf("%c", *(char *)&iov->iov_base[i]); - } - log_printf("] vq->last_avail_idx is %d\n", vq->last_avail_idx); - } if (len < 0 && errno == EWOULDBLOCK) { log_debug("no more bytes"); vq->last_avail_idx--; @@ -158,32 +152,12 @@ static void virtq_tx_handle_one_request(ConsoleDev *dev, VirtQueue *vq) { uint16_t idx; ssize_t len; struct iovec *iov = NULL; - static int count = 0; - count++; if (dev->master_fd <= 0) { log_error("Console master fd is not ready"); return; } n = process_descriptor_chain(vq, &idx, &iov, NULL, 0, false); - // if (count % 100 == 0) { - // log_info("console txq: n is %d, data is ", n); - // for (int i=0; iiov_len; i++) - // log_printf("%c", *(char*)&iov->iov_base[i]); - // log_printf("\n"); - // } - - for (int i = 0; i < n; i++) { - log_printf("RAW:["); - for (int j = 0; j < iov[i].iov_len; j++) { - char x = *(char *)&iov[i].iov_base[j]; - if (x == '\t' || x == '\n' || x == '\r') { - x = ' '; - } - log_printf("%c", x); - } - log_printf("]\n"); - } if (n < 1) { return; From 925ba7425c29640f4787aaf51620e74188b98ded Mon Sep 17 00:00:00 2001 From: Guowei Li <15035660024@163.com> Date: Tue, 27 Jan 2026 14:30:36 +0800 Subject: [PATCH 2/4] fix(log): correct spelling of multithread_log_exit function This commit fixes a typo in the function name multithread_log_exit, which was incorrectly spelled as mutithread_log_exit in the log.c and virtio.c files. The header file log.h has also been updated to reflect this correction. --- tools/include/log.h | 2 +- tools/log.c | 2 +- tools/virtio.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/include/log.h b/tools/include/log.h index 4537e4b..4f2be13 100644 --- a/tools/include/log.h +++ b/tools/include/log.h @@ -38,5 +38,5 @@ void log_set_quiet(bool enable); void log_log(int level, const char *file, int line, const char *fmt, ...); void multithread_log_init(); -void mutithread_log_exit(); +void multithread_log_exit(); #endif diff --git a/tools/log.c b/tools/log.c index 0d0ab0e..e24b773 100644 --- a/tools/log.c +++ b/tools/log.c @@ -71,4 +71,4 @@ void multithread_log_init() { openlog("hvisor-tool", LOG_PID | LOG_NDELAY, LOG_DAEMON); } -void mutithread_log_exit() { closelog(); } \ No newline at end of file +void multithread_log_exit() { closelog(); } \ No newline at end of file diff --git a/tools/virtio.c b/tools/virtio.c index 335934b..ec7b5d5 100644 --- a/tools/virtio.c +++ b/tools/virtio.c @@ -1010,7 +1010,7 @@ void virtio_close() { zone_mem[i][j][MEM_SIZE]); } } - mutithread_log_exit(); + multithread_log_exit(); log_warn("virtio daemon exit successfully"); } From e6ec801eb48d8b0e07193535a52d482ab42afc03 Mon Sep 17 00:00:00 2001 From: Guowei Li <15035660024@163.com> Date: Tue, 27 Jan 2026 19:11:18 +0800 Subject: [PATCH 3/4] docs: update README to clarify daemon startup and logging This commit updates the README files in both English and Chinese to clarify the command for starting the Virtio daemon and the logging mechanisms. The `nohup ... &` command has been simplified to `&`, and instructions for viewing logs have been added for both `systemd` and non-`systemd` systems. Additionally, the reference to `nohup.out` has been replaced with `syslog` for log retrieval instructions. --- README-zh.md | 17 +++++++++++++---- README.md | 15 ++++++++++++--- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/README-zh.md b/README-zh.md index 47bdf59..4af2e5f 100644 --- a/README-zh.md +++ b/README-zh.md @@ -108,13 +108,22 @@ hvisor_virtio_device { ```c // 注意要先启动守护进程,再启动各个zones -nohup ./hvisor virtio start virtio_cfg.json & +./hvisor virtio start virtio_cfg.json & ./hvisor zone start ``` -其中`nohup ... &`说明该命令会创建一个守护进程,且该进程的日志输出保存在当前文件夹下的nohup.out文件中。 +其中 `&` 说明该命令会在后台运行。由于 Virtio 守护进程使用 `syslog` 记录日志,使用以下命令查看 `hvisor-tool` 的日志: -`virtio_cfg.json`则是一个描述Virtio设备的JSON文件,例如[virtio_cfg.json](./examples/nxp-aarch64/virtio_cfg.json)。该示例文件会依次执行: +* **对于使用 `systemd` 的系统:** + ```bash + journalctl -t hvisor-tool -f + ``` +* **对于没有 `systemd` 的系统(日志由 `rsyslog` 处理):** + ```bash + tail -f /var/log/syslog | grep hvisor-tool + ``` + +`virtio_cfg.json` 则是一个描述Virtio设备的JSON file,例如[virtio_cfg.json](./examples/nxp-aarch64/virtio_cfg.json)。该示例文件会依次执行: 1. 地址空间映射 @@ -126,7 +135,7 @@ nohup ./hvisor virtio start virtio_cfg.json & 3. 创建Virtio-console设备 -创建一个Virtio-console设备,用于`zone1`主串口的输出。root linux需要执行`screen /dev/pts/x`命令进入该虚拟控制台,其中`x`可通过nohup.out日志文件查看。 +创建一个Virtio-console设备,用于`zone1`主串口的输出。root linux需要执行`screen /dev/pts/x`命令进入该虚拟控制台,其中`x`可通过syslog日志查看。 如要退回到主控制台,按下快捷键`ctrl+a+d`。如果在qemu中,则需要按下`ctrl+a ctrl+a+d`。如要再次进入虚拟控制台,执行`screen -r [SID]`,其中SID为该screen会话的进程ID。 diff --git a/README.md b/README.md index 73879f5..58e1fd6 100644 --- a/README.md +++ b/README.md @@ -108,11 +108,20 @@ On Root Linux, execute the following example commands: ```c // Note: Start the daemon before starting the zones -nohup ./hvisor virtio start virtio_cfg.json & +./hvisor virtio start virtio_cfg.json & ./hvisor zone start ``` -The `nohup ... &` part indicates that this command will create a daemon, and its log output will be saved in the `nohup.out` file in the current directory. +The `&` part indicates that this command will run in the background. Since the Virtio daemon uses `syslog` for logging, use the following commands to view the `hvisor-tool` logs: + +* **For systems with `systemd`:** + ```bash + journalctl -t hvisor-tool -f + ``` +* **For systems without `systemd` (logs are handled by `rsyslog`):** + ```bash + tail -f /var/log/syslog | grep hvisor-tool + ``` `virtio_cfg.json` is a JSON file that describes the Virtio devices, such as [virtio_cfg.json](./examples/nxp-aarch64/virtio_cfg.json). The example file will perform the following actions: @@ -126,7 +135,7 @@ A Virtio-blk device is created, and `zone1` will communicate with this device vi 3. **Create Virtio-console Device** -A Virtio-console device is created for the main serial port of `zone1`. Root Linux should execute the command `screen /dev/pts/x` to enter this virtual console, where `x` can be found in the `nohup.out` log file. +A Virtio-console device is created for the main serial port of `zone1`. Root Linux should execute the command `screen /dev/pts/x` to enter this virtual console, where `x` can be found in the system log. To return to the main console, press the shortcut `ctrl+a+d`. In QEMU, press `ctrl+a ctrl+a+d`. To re-enter the virtual console, execute `screen -r [SID]`, where SID is the process ID of the `screen` session. From f33c9dd6cb94011fc81c8f667a736dc13a6ffe66 Mon Sep 17 00:00:00 2001 From: Guowei Li <15035660024@163.com> Date: Tue, 27 Jan 2026 19:27:36 +0800 Subject: [PATCH 4/4] docs: update README to use nohup for daemon startup This commit updates the README files in both English and Chinese to specify the use of `nohup` when starting the Virtio daemon. This change ensures that the daemon continues running even after the terminal is closed, improving usability for users. No other changes were made to the content. --- README-zh.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README-zh.md b/README-zh.md index 4af2e5f..b5eb892 100644 --- a/README-zh.md +++ b/README-zh.md @@ -108,7 +108,7 @@ hvisor_virtio_device { ```c // 注意要先启动守护进程,再启动各个zones -./hvisor virtio start virtio_cfg.json & +nohup ./hvisor virtio start virtio_cfg.json & ./hvisor zone start ``` diff --git a/README.md b/README.md index 58e1fd6..276bd42 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ On Root Linux, execute the following example commands: ```c // Note: Start the daemon before starting the zones -./hvisor virtio start virtio_cfg.json & +nohup ./hvisor virtio start virtio_cfg.json & ./hvisor zone start ```