对于一个从单片机开发转向操作系统中的应用程序开发的攻城狮来说,对程序的调试方法的转换也是非常重要的。单片机的开发,一般使用jlink进行单步调试较多,但是对于在操作系统上进行应用程序一般都是比较庞大的,所以再使用单片机开发的调试思维就不现实啦。最常见的就是使用printf打印与syslog日志打印,对于printf的使用比较简单,所以这里主要介绍一下syslog的用法。
syslog的调试信息的打印是后台运行的,不占用控制台。并且可以进行调试信息级别的控制,这样可以避免输出很多无用的信息,让观看者可以更快的找到希望看到的信息。
对于linux系统中提供的日志打印服务,提供了一些库函数,一般使用的就是三个,openlog()、syslog()、closelog()
#include
void openlog(const char *ident, int option, int facility);
void syslog(int priority, const char *format, ...);
void closelog(void);
void openlog(const char *ident, int option, int facility); 用于打开系统记录
LOG_CONS
直接写入系统控制台,如果有一个错误,同时发送到系统日志记录。
LOG_NDELAY
立即打开连接(通常,打开连接时记录的第一条消息)。
LOG_NOWAIT
不要等待子进程,因为其有可能在记录消息的时候就被创建了(GNU C库不创建子进程,所以该选项在Linux上没有影响。)
LOG_ODELAY
延迟连接的打开直到syslog函数调用。(这是默认情况下,需要没被指定的情况下。)
LOG_PERROR
(不在SUSv3情况下)同时输出到stderr(标准错误文件)。
LOG_PID
包括每个消息的PID。
facility
The facility argument is used to specify what type of program is logging the message. This lets the configuration file
specify that messages from different facilities will be handled differently.
LOG_AUTH security/authorization messages
LOG_AUTHPRIV security/authorization messages (private)
LOG_CRON clock daemon (cron and at)
LOG_DAEMON system daemons without separate facility value
LOG_FTP ftp daemon
LOG_KERN kernel messages (these can't be generated from user processes)
LOG_LOCAL0 through LOG_LOCAL7
reserved for local use
LOG_LPR line printer subsystem
LOG_MAIL mail subsystem
LOG_NEWS USENET news subsystem
LOG_SYSLOG messages generated internally by syslogd(8)
LOG_USER (default)
generic user-level messages
LOG_UUCP UUCP subsystem
void syslog(int priority, const char *format, ...); 记录至系统记录
LOG_EMERG:紧急情况,需要立即通知技术人员。
LOG_ALERT:应该被立即改正的问题,如系统数据库被破坏,ISP连接丢失。
LOG_CRIT:重要情况,如硬盘错误,备用连接丢失。
LOG_ERR:错误,不是非常紧急,在一定时间内修复即可。
LOG_WARNING:警告信息,不是错误,比如系统磁盘使用了85%等。
LOG_NOTICE:不是错误情况,也不需要立即处理。
LOG_INFO:情报信息,正常的系统消息,比如骚扰报告,带宽数据等,不需要处理。
LOG_DEBUG:包含详细的开发情报的信息,通常只在调试一个程序时使用。
void closelog(void); 关闭日志文件,这个函数就没有什么好说的啦,没有任何参数,直接关闭日志文件。
#include
#include
#include
#include
int main(void)
{
printf("my pid = %d.\n", getpid());
/*在日志中虽然写了文件名,但是出于准确考虑,也会显示该进程的pid,因为pid才是一个进程的唯一标识*/
openlog("a.out", LOG_PID | LOG_CONS, LOG_USER);
syslog(LOG_INFO, "this is my log info.%d", 23); //使用方法与printk 类似可以格式化的输出
syslog(LOG_INFO, "this is another log info.");
syslog(LOG_INFO, "this is 3th log info.");
closelog();
}
在Ubuntu中日志在/var/log/syslog文件中,不同linux的发行版路径会不一样,其他的日志可能会在/var/log/messages
(1)操作系统中有一个守护进程syslogd(开机运行,关机时才结束),这个守护进程syslogd负责进行日志文件的写入和维护。
(2)syslogd是独立于我们任意一个进程而运行的。我们当前进程和syslogd进程本来是没有任何关系的,但是我们当前进程可以通过调用openlog打开一个和syslogd相连接的通道,然后通过syslog向syslogd发消息,然后由syslogd来将其写入到日志文件系统中。
(3)syslogd其实就是一个日志文件系统的服务器进程,提供日志服务。任何需要写日志的进程都可以通过openlog/syslog/closelog这三个函数来利用syslogd提供的日志服务。这就是操作系统的服务式的设计。
注明:本博客是根据朱有鹏老师的l《linux嵌入式核心课程》视频所作的总结