initlog

合集下载

Linux系统rc.sysinit文件详解

Linux系统rc.sysinit文件详解

/etc/rc.d/rc.sysinit 文件详解#!/bin/bash## /etc/rc.d/rc.sysinit - run once at boot time### Rerun ourselves through initlog // 通过/sbin/initlog 命令重新运行自己if [ -z "$IN_INITLOG" -a -x /sbin/initlog ]; then // 条件是:如果IN_INITLOG 变量的值不为空,且/sbin/initlog 可执行exec /sbin/initlog -r /etc/rc.d/rc.sysinit // 调用exec /sbin/initlog ,-r 是表示运行某个程序fi################################################ ################################################ ################################################ ######HOSTNAME=`/bin/hostname` # 取得主机名HOSTTYPE=`uname -m` # 取得主机类型unamer=`uname -r` # 取得内核的release 版本(例如2.4.9.30-8)eval version=`echo $unamer | awk -F '.' '{ print "(" $1 " " $2 ")" }'` # 取得版本号if [ -f /etc/sysconfig/network ]; then # 如果存在/etc/sysconfig/network ,则执行该文件。

. /etc/sysconfig/network # network 文件主要控制是否启用网络、默认网关、主机名fiif [ -z "$HOSTNAME" -o "$HOSTNAME" = "(none)" ]; then # 如果执行network 文件后HOSTNAME 为空或者为"(none)" ,HOSTNAME=localhost # 则将主机名设置为"localhost"fi# Mount /proc and /sys (done here so volume labels can work with fsck) # 接下来是挂载/proc 和/sys ,这样fsck 才能使用卷标mount -n -t proc /proc/proc # -n 表示不写/etc/mtab ,这在/etc 所在的文件系统为只读时用。

init启动流程分析

init启动流程分析

init启动流程分析现在通用的发行的linux版本包括两种init,一种是老式的system V initialization,另一种是新式的Upstart方式。

system V initialization是基于启动等级的守护进程,他使用运行级别和链接来启动和关闭服务;Upstart init进程是基于事件的的守护进程,它使用事件来启动和关闭系统服务。

两种方式都有自己的启动流程,之前在查找Linux系统init流程的相关资料时总能够看到inittab,但是最新的Ubuntu上不存在这个文件,在旧式的System V initialization中,/etc/inittab可是个相当重要的文件。

init进程启动后第一时间找到它!inittab负责初始化系统,设置系统runlevel及进入各runlevel对应要执行的命令。

如果当前inittab中设置的默认runlevle是5,则init会运行/etc/init.d/rc 5命令,该命令会依据系统服务的依赖关系遍历执行/etc/rc5.d中的脚本/程序。

进入/etc/rc5.d目录,可以发现里面的文件都是到/etc /init.d/下对应的脚本/程序的软链接。

以S开头的为启动的意思,以K开头的为停止。

并且S/K后面的两位数字代表了服务的启动顺序。

在Upstart 方式中,runlevel对于服务的启动也有影响但不是关键所在。

Upstart job是事件驱动的,系统服务的启动、停止等等均是由事件决定的,反过来,系统服务的启动、停止也可以作为事件源触发其他服务。

并且事件并不一定得由系统内部产生,用户可以手工的键入start/stop [Service]产生事件来启动/终止服务。

man upstart-evnets查看upstart job所定义的事件,可以发现,runlevel也被当作事件来对待(因runlevel的改变而产生的事件),诸如此类还有其他如startup,started,filesystem等等。

init rc加日志方法

init rc加日志方法

init rc加日志方法
在Linux系统中,init是系统的第一个进程,它负责启动和管理系统中的所有其他进程。

init进程的配置文件通常是位于/etc目录下的init/rc文件,不同的Linux发行版可能会有不同的命名方式,比如Ubuntu使用的是upstart或者systemd。

要给init/rc添加日志方法,你可以使用syslog服务来记录系统日志信息。

syslog是一个系统日志服务,它可以帮助你收集、记录和管理系统的各种日志信息。

你可以在init/rc脚本中调用syslog服务来记录特定事件或者输出信息。

另一种方法是在init/rc脚本中直接调用logger命令来记录日志。

logger命令可以将指定的消息写入系统日志中,你可以在
init/rc脚本中使用logger命令来记录系统启动、关闭或者其他重要事件的日志信息。

此外,你还可以在init/rc脚本中使用echo命令将日志信息输出到特定的文件中,这样可以方便你查看和分析系统的运行日志。

总的来说,要给init/rc添加日志方法,你可以使用syslog服
务、logger命令或者echo命令来记录系统日志信息,这样可以帮助你更好地监控和管理系统的运行情况。

1)reboot 重启(2)init 6 重启(3)logo

1)reboot 重启(2)init 6 重启(3)logo

1)reboot 重启(2)init 6 重启(3)logo1.1一般在linux中,我们重启会用到这三个命令:1.2 reboot命令重启动系统时是删除所有的进程,而不是平稳地终止它们。

因此,使用reboot命令可以快速地关闭系统,但如果还有其它用户在该系统上工作时,就会引起数据的丢失。

所以使用reboot命令的场合主要是在单用户模式。

'reboot'并不执行这些过程,reboot更是一个kernel级别的命令,不对应用使用shutdown脚本。

1.3 init是所有进程的祖先他是Linux系统操作中不可缺少的程序之一。

它的进程号始终为1所以发送TERM信号给init 会终止所有的用户进程守护进程等。

shutdown 就是使用这种机制。

init定义了7个运行级别(runlevel)init 0为关机init 6为重启。

’init 6‘基于一系列/etc/inittab文件,并且每个应用都会有一个相应shutdown脚本。

'init 6' 调用一系列shutdown脚本(/etc/rc0.d/K*)来使系统正常关机;1.4 shutdown命令可以安全地关闭或重启Linux系统,它在系统关闭之前给系统上的所有登录用户提示一条警告信息。

该命令还允许用户指定一个时间参数,可以是一个精确的时间,也可以是从现在开始的一个时间段。

精确时间的格式是hh:mm,表示小时和分钟,时间段由+ 和分钟数表示。

系统执行该命令后会自动进行数据同步的工作。

该命令的一般格式: shutdown [选项] [时间] [警告信息]命令中各选项的含义为:- k 并不真正关机而只是发出警告信息给所有用户- r 关机后立即重新启动- h 关机后不重新启动- f 快速关机重启动时跳过fsck- n 快速关机不经过init 程序- c 取消一个已经运行的shutdown请注意,该命令只能由超级用户使用。

鸿蒙的DFX子系统

鸿蒙的DFX子系统

鸿蒙的DFX⼦系统作者:liangkz 更新时间:2021.05.05我们仍然是先对⼦系统的⽬录结构做⼀次整理,做成表格,把模块之间的调⽤关系理⼀下:1. Hi3861 平台如上表,上电后在SystemInit阶段会依次init:HiviewConfigInit、HiLogInit、hiview service:[system_init] HOS_SystemInit begin: %%%%%%%%%%%[system_init] MODULE_INIT(core)============================[hiview_config] CORE_INIT_PRI(HiviewConfigInit, 0);[hiview_log] HiLogInit. CORE_INIT_PRI(HiLogInit, 0)[hiview_output_log] InitCoreLogOutput. call HiviewRegisterMsgHandle[system_init] SYS_INIT(service)============================[hiview_service] SYS_SERVICE_INIT(Init).[samgr_lite] RegisterService(name: hiview)[hiview_service] Init.InitHiviewComponent.[hiview_file] InitHiviewFile............[hiview_service] Initialize.我们分别来看⼀下他们都做了些什么事情:A. HiviewConfigInit位于:Hi3861/base/hiviewdfx/utils/lite/hiview_config.c其主要是初始化全局变量g_hiviewConfig的配置,如下hiviewInited:标记hiview service是否已经完成初始化。

Linux下var目录介绍

Linux下var目录介绍

Linux下var⽬录介绍var⽬录/var 包括系统运⾏时要改变的数据。

其中包括每个系统是特定的,即不能够与其他计算机共享的⽬录,如/var/log,/var/lock,/var/run。

有些⽬录还是可以与其他系统共享,如/var/mail, /var/cache/man, /var/cache/fonts,/var/spool/news。

var⽬录存在的⽬的是把usr⽬录在运⾏过程中需要更改的⽂件或者临时⽣成的⽂件及⽬录提取出来,由此可以使usr⽬录挂载为只读的⽅式。

隐含要求var⽬录必须挂载为可以读写的⽅式。

通过对于该⽬录的分析注意如下的需要1)各个⽬录存在的⽬的以及作⽤。

2)通过⽬录中的信息能够获得什么信息,如何对于该信息进⾏访问。

3)对于⽬录中的⽂件操作是否安全。

/var/account/pact⽬的:该⽬录保存系统中使⽤的进程记录。

当⼀个进程终⽌时,把每个进程向统计⽂件(pacct或acct)中写⼀个纪录。

进程统计的⽬的是为系统中的基本服务提供命令使⽤统计。

该⽂件可以通过数据的⼯具(sa,ac)进⾏分析。

使⽤:进程统计⼦系统缺省不激活,它必须启动。

在Linux系统中启动进程统计使⽤accton命令,必须⽤root⾝份来运⾏。

accton命令的形式accton file,file必须先存在。

如果不存在则先使⽤touch命令来创建pacct⽂件:touch /var/log/pacct,然后运⾏accton: accton/var/account/pacct。

⼀旦accton被激活,就可以使⽤lastcomm命令监测系统中任何时候执⾏的命令。

若要关闭统计,可以使⽤不带任何参数的accton命令。

pact⽂件不可⽤cat直接读取其中的内容。

注意:该⽂件会⼤量增长,需要注意维护(删除,转储)/var/crash⽬的:系统崩溃时转储的⽂件,可以通过该⽂件分析down机的原因。

使⽤: crash⼯具对于该⽬录中的⽂件进⾏分析。

syslog日志服务器配置步骤

syslog日志服务器配置步骤

syslog日志服务器配置步骤一.作用Linux 系统的日志主要分为两种类型 :1. 进程所属日志:由用户进程或其他系统服务进程自行生成的日志,比如服务器上的access_log 与 error_log 日志文件。

2. syslog 消息:系统syslog 记录的日志,任何希望记录日志的系统进程或者用户进程都可以给调用syslog来记录日志。

Syslog程序就是用来记录这类日志的。

syslog是Linux的日志子系统,日志文件详细地记录了系统每天发生的各种各样的事件。

用户可以通过日志文件检查错误产生的原因,或者在受到攻击和黑客入侵时追踪攻击者的踪迹。

日志的两个比较重要的作用是:审核和监测。

配置syslog中央服务器能够使所有服务器的系统信息都集中到某台特定的机器上,便于对集群中机器的管理与检查Linux系统所有的日志文件都在/var/log下,且必须有 root 权限才能察看。

日志文件其实是纯文本的文件,每一行表示一个消息,而且都由四个域的固定格式组成:1. 时间标签 (timestamp ),表示消息发出的日期和时间。

2. 主机名( hostname ),表示生成消息的计算机的名字。

如果只有一台计算机,主机名就可能没有必要了。

但是如果在网络环境中使用 syslog,那么就可能要把不同主机的消息发送到一台服务器上集中处理。

3. 生成消息的子系统的名字。

可以是”kernel”,表示消息来自内核;或者是进程的名字,表示发出消息的程序的名字。

在方括号里的是进程的PID。

4. 消息( message ),剩下的部分就是消息的内容。

二.syslog配置文件syslog是Linux系统默认的日志守护进程。

默认的syslog配置文件是/etc/syslog.conf文件。

syslog守护进程是可配置的,它允许人们为每一种类型的系统信息精确地指定一个存放地点。

现在,我们先看看syslog.conf文件的配置行格式(这个文件里的每一个配置行都是同样的格式),然后再看一个完整的syslog配置文件。

Linux init详解

Linux init详解

Linux init详解一、什么是INIT:init是Linux系统操作中不可缺少的程序之一。

所谓的init进程,它是一个由内核启动的用户级进程。

内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。

所以,init始终是第一个进程(其进程编号始终为1)。

内核会在过去曾使用过init的几个地方查找它,它的正确位置(对Linux系统来说)是/sbin/init。

如果内核找不到init,它就会试着运行/bin/sh,如果运行失败,系统的启动也会失败。

二、运行级别那么,到底什么是运行级呢?简单的说,运行级就是操作系统当前正在运行的功能级别。

这个级别从1到6 ,具有不同的功能。

不同的运行级定义如下:(可以参考Red Hat Linux 里面的/etc/inittab)# 0 - 停机(千万不能把initdefault 设置为0 )# 1 - 单用户模式# 2 - 多用户,没有 NFS# 3 - 完全多用户模式(标准的运行级)# 4 - 没有用到# 5 - X11 (xwindow)# 6 - 重新启动(千万不要把initdefault 设置为6 )这些级别在/etc/inittab 文件里指定。

这个文件是init 程序寻找的主要文件,最先运行的服务是放在/etc/rc.d 目录下的文件。

在大多数的Linux 发行版本中,启动脚本都是位于 /etc/rc.d/init.d中的。

这些脚本被用ln 命令连接到 /etc/rc.d/rcn.d 目录。

(这里的n 就是运行级0-6)三、运行级别的配置运行级别的配置是在/etc/inittab行内进行的,如下所示:12 : 2 : wait : / etc / init.d / rc 2第一个字段是一个任意指定的标签;第二个字段表示这一行适用于运行那个级别(这里是2);第三个字段表示进入运行级别时,init应该运行第四个字段内的命令一次,而且init应该等待该命令结束。

Androidinit启动过程分析-gpephone

Androidinit启动过程分析-gpephone

Androidinit启动过程分析-gpephoneAndroid init 启动过程分析分析android的启动过程,从内核之上,我们首先应该从文件系统的init开始,因为init 是内核进入文件系统后第一个运行的程序,通常我们可以在linux的命令行中指定内核第一个调用谁,如果没指定那么内核将会到/sbin/, /bin/ 等目录下查找默认的init,如果没有找到那么就报告出错。

下面是曾经用过的几种开发板的命令行参数:S3C2410 启动参数:noinitrdroot=/dev/nfs nfsroot=192.168.2.56:/nfsroot/rootfs ip=192.16 8.2.188:192.168.2.56:192.168.2.56:255.255.255.0::eth0:on console=ttySAC0S3C2440 启动参数:setenv bootargs console=ttySAC0 root=/dev/nfs nfsroot=192.168.2.56:/nfsroot/rootfsip=192.168.2.175:192.168.2.56:192.168.2.201:255.255.255.0::eth0 :on mem=64M init=/initmarvell 310 启动参数:boot root=/dev/nfs nfsroot=192.168.2.56:/nfsroot/rootfs,rsize=1024,wsize=1024ip=192.168.2.176:192.168.2.201:192.168.2.201:255.255.255.0::eth 0:-On console=ttyS2,115200 mem=64M init=/initinit的源代码在文件:./system/core /init/init.c 中,init会一步步完成下面的任务:1.初始化log系统2.解析/init.rc和 /init.%hardware%.rc文件3. 执行 early-init action in the two files parsed in step 2.4. 设备初始化,例如:在/dev 下面创建所有设备节点,下载firmwares.5. 初始化属性服务器,Actually the property system is working as a share memory. Logically it looks like a registry under Windows system.6. 执行 init action in the two files parsed in step 2.7. 开启属性服务。

Qt编写软件运行时间记录(开源)

Qt编写软件运行时间记录(开源)

Qt编写软件运⾏时间记录(开源)#ifndef SAVERUNTIME_H#define SAVERUNTIME_H#include <QObject>#include <QDateTime>class QTimer;#ifdef quc#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))#include <QtDesigner/QDesignerExportWidget>#else#include <QtUiPlugin/QDesignerExportWidget>#endifclass QDESIGNER_WIDGET_EXPORT SaveRunTime : public QObject#elseclass SaveRunTime : public QObject#endif{Q_OBJECTpublic:static SaveRunTime *Instance();explicit SaveRunTime(QObject *parent = 0);private:static QScopedPointer<SaveRunTime> self;QString path; //⽇志⽂件路径QString name; //⽇志⽂件名称int lastID;int saveInterval;QDateTime startTime;QString logFile;QTimer *timerSave;private:void getDiffValue(const QDateTime &startTime, const QDateTime &endTime, int &day, int &hour, int &minute);signals:public slots:void start(); //启动服务void stop(); //停⽌服务void initLog(); //初始化⽇志⽂件void appendLog(); //追加⼀条记录到⽇志⽂件void saveLog(); //保存运⾏时间到⽇志⽂件void setPath(const QString &path);void setName(const QString &name);void setSaveInterval(int saveInterval);};#endif// SAVERUNTIME_H#include "saveruntime.h"#include "qmutex.h"#include "qapplication.h"#include "qtimer.h"#include "qfile.h"#include "qtextstream.h"#include "qstringlist.h"#include "qdebug.h"#ifdef Q_OS_WIN#define NEWLINE "\r\n"#else#define NEWLINE "\n"#endifQScopedPointer<SaveRunTime> SaveRunTime::self;SaveRunTime *SaveRunTime::Instance(){if (self.isNull()) {QMutex mutex;QMutexLocker locker(&mutex);if (self.isNull()) {self.reset(new SaveRunTime);}}return self.data();}SaveRunTime::SaveRunTime(QObject *parent) : QObject(parent){path = qApp->applicationDirPath();QString str = qApp->applicationFilePath();QStringList list = str.split("/");name = list.at(list.count() - 1).split(".").at(0);saveInterval = 1 * 60 * 1000;startTime = QDateTime::currentDateTime();timerSave = new QTimer(this);timerSave->setInterval(saveInterval);connect(timerSave, SIGNAL(timeout()), this, SLOT(saveLog()));}void SaveRunTime::start(){timerSave->start();initLog();appendLog();saveLog();}void SaveRunTime::stop(){timerSave->stop();}void SaveRunTime::getDiffValue(const QDateTime &startTime, const QDateTime &endTime, int &day, int &hour, int &minute) {qint64 sec = startTime.secsTo(endTime);day = hour = minute = 0;int seconds = 0;while (sec > 0) {seconds++;if (seconds == 60) {minute++;seconds = 0;}if (minute == 60) {hour++;minute = 0;}if (hour == 24) {day++;hour = 0;}sec--;}}void SaveRunTime::initLog(){//判断当前年份的记事本⽂件是否存在,不存在则新建并且写⼊标题//存在则⾃动读取最后⼀⾏的id号记事本⽂件格式内容//编号开始时间结束时间已运⾏时间//1 2016-01-01 12:33:33 2016-02-05 12:12:12 day: 0 hour: 0 minute: 0logFile = QString("%1/%2_runtime_%3.txt").arg(path).arg(name).arg(QDate::currentDate().year());QFile file(logFile);if (file.size() == 0) {if (file.open(QFile::WriteOnly | QFile::Text)) {QString strID = QString("%1\t").arg("编号");QString strStartTime = QString("%1\t\t").arg("开始时间");QString strEndTime = QString("%1\t\t").arg("结束时间");QString strRunTime = QString("%1").arg("已运⾏时间");QString line = strID + strStartTime + strEndTime + strRunTime;QTextStream stream(&file);stream << line << NEWLINE;file.close();lastID = 0;}} else {if (file.open(QFile::ReadOnly)) {QString lastLine;while (!file.atEnd()) {lastLine = file.readLine();}file.close();QStringList list = lastLine.split("\t");lastID = list.at(0).toInt();}}lastID++;}void SaveRunTime::appendLog(){logFile = QString("%1/%2_runtime_%3.txt").arg(path).arg(name).arg(QDate::currentDate().year());QFile file(logFile);//写⼊当前⾸次运⾏时间if (file.open(QFile::WriteOnly | QFile::Append | QFile::Text)) {QString strID = QString("%1\t").arg(lastID);QString strStartTime = QString("%1\t").arg(startTime.toString("yyyy-MM-dd HH:mm:ss"));QString strEndTime = QString("%1\t").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));int day, hour, minute;getDiffValue(startTime, QDateTime::currentDateTime(), day, hour, minute);QString strRunTime = QString("%1 天 %2 时 %3 分").arg(day).arg(hour).arg(minute);QString line = strID + strStartTime + strEndTime + strRunTime;QTextStream stream(&file);stream << line << NEWLINE;file.close();}}void SaveRunTime::saveLog(){//每次保存都是将之前的所有⽂本读取出来,然后替换最后⼀⾏即可logFile = QString("%1/%2_runtime_%3.txt").arg(path).arg(name).arg(QDate::currentDate().year());QFile file(logFile);//如果⽇志⽂件不存在,则初始化⼀个⽇志⽂件if (file.size() == 0) {initLog();appendLog();return;}if (file.open(QFile::ReadWrite)) {//⼀⾏⾏读取到链表QStringList content;while (!file.atEnd()) {content.append(file.readLine());}//重新清空⽂件file.resize(0);//如果⾏数⼩于2则返回if (content.count() < 2) {file.close();return;}QString lastLine = st();QStringList list = lastLine.split("\t");//计算已运⾏时间int day, hour, minute;getDiffValue(startTime, QDateTime::currentDateTime(), day, hour, minute);QString strRunTime = QString("%1 天 %2 时 %3 分").arg(day).arg(hour).arg(minute);//重新拼接最后⼀⾏list[2] = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");list[3] = strRunTime;lastLine = list.join("\t");//重新替换最后⼀⾏并写⼊新的数据content[content.count() - 1] = lastLine;QTextStream stream(&file);stream << content.join("") << NEWLINE;file.close();}}void SaveRunTime::setPath(const QString &path) {if (this->path != path) {this->path = path;}}void SaveRunTime::setName(const QString &name) {if (this->name != name) {this->name = name;}}void SaveRunTime::setSaveInterval(int saveInterval) {if (this->saveInterval != saveInterval) {this->saveInterval = saveInterval;timerSave->setInterval(saveInterval);}}。

编译 undefined reference to `initdltlog'

编译 undefined reference to `initdltlog'

编译 undefined reference to `initdltlog' 问题描述:在编译过程中,出现了undefined reference to `initdltlog'的错误。

该错误通常是由于链接器找不到所需的库或符号导致的。

在此情况下,链接器无法解析initdltlog符号,并报告未定义的引用错误。

解决方案:出现此错误时,通常需要检查编译器是否正确链接所需的库文件。

首先,可以尝试在编译命令中添加-l选项,以指定链接库的名称。

例如,如果所需的库名称为libdltlog.so,则可以使用以下命令:
gcc -o myprogram myprogram.c -ldltlog
此命令将链接名为libdltlog.so的库文件,并将生成的可执行文件命名为myprogram。

如果仍然出现错误,则需要检查库文件是否正确安装和配置。

可以使用ldd命令检查库文件是否正确链接。

例如,可以使用以下命令检查libdltlog.so是否正确链接:
ldd /usr/lib/libdltlog.so
此命令将显示链接库的依赖关系,并指出是否找到了所需的库文件。

如果库文件已正确安装并链接,但错误仍然存在,则可能是由于编译器版本不兼容或编译选项不正确导致的。

在此情况下,需要检查编译器版本和编译选项,并尝试使用不同的版本或选项进行编译。

总之,处理undefined reference to `initdltlog'错误的关键
是确定所需的库文件是否正确链接,并根据需要进行调整。

Android系统启动流程(一)解析init进程

Android系统启动流程(一)解析init进程

Android系统启动流程(一)解析init进程前言作为“Android框架层”这个大系列中的第一个系列,我们首先要了解的是Android系统启动流程,在这个流程中会涉及到很多重要的知识点,这个系列我们就来一一讲解它们,这一篇我们就来学习init进程。

1.init简介init进程是Android系统中用户空间的第一个进程,作为第一个进程,它被赋予了很多极其重要的工作职责,比如创建zygote(孵化器)和属性服务等。

init进程是由多个源文件共同组成的,这些文件位于源码目录system/core/init。

本文将基于Android7.0源码来分析Init进程。

2.引入init进程说到init进程,首先要提到Android系统启动流程的前几步:1.启动电源以及系统启动当电源按下时引导芯片代码开始从预定义的地方(固化在ROM)开始执行。

加载引导程序Bootloader到RAM,然后执行。

2.引导程序Bootloader引导程序是在Android操作系统开始运行前的一个小程序,它的主要作用是把系统OS拉起来并运行。

3.Linux内核启动内核启动时,设置缓存、被保护存储器、计划列表,加载驱动。

当内核完成系统设置,它首先在系统文件中寻找”init”文件,然后启动root进程或者系统的第一个进程。

4.init进程启动讲到第四步就发现我们这一节要讲的init进程了。

关于Android系统启动流程的所有步骤会在本系列的最后一篇做讲解。

3.init入口函数init的入口函数为main,代码如下所示。

system/core/init/init.cppint main(int argc, char** argv) {if (!strcmp(basename(argv[0]), "ueventd")) {return ueventd_main(argc, argv);}if (!strcmp(basename(argv[0]), "watchdogd")) {return watchdogd_main(argc, argv);}umask(0);add_environment("PATH", _PATH_DEFPATH);bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);//创建文件并挂载if (is_first_stage) {mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");mkdir("/dev/pts", 0755);mkdir("/dev/socket", 0755);mount("devpts", "/dev/pts", "devpts", 0, NULL);#define MAKE_STR(x) __STRING(x)mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));mount("sysfs", "/sys", "sysfs", 0, NULL);}open_devnull_stdio();klog_init();klog_set_level(KLOG_NOTICE_LEVEL);NOTICE("init %s started!\n", is_first_stage ? "first stage" : "second stage");if (!is_first_stage) {// Indicate that booting is in progress to background fw loaders, etc.close(open("/dev/.booting", O_WRONL Y | O_CREAT | O_CLOEXEC, 0000));//初始化属性相关资源property_init();//1process_kernel_dt();process_kernel_cmdline();export_kernel_boot_props();}...//启动属性服务start_property_service();//2const BuiltinFunctionMap function_map;Action::set_function_map(&function_map);Parser& parser = Parser::GetInstance();parser.AddSectionParser("service",std::make_unique<ServiceParser>());parser.AddSectionParser("on", std::make_unique<ActionParser>());parser.AddSectionParser("import", std::make_unique<ImportParser>());//解析init.rc配置文件parser.ParseConfig("/init.rc");//3...while (true) {if (!waiting_for_exec) {am.ExecuteOneCommand();restart_processes();}int timeout = -1;if (process_needs_restart) {timeout = (process_needs_restart - gettime()) * 1000;if (timeout < 0)timeout = 0;}if (am.HasMoreCommands()) {timeout = 0;}bootchart_sample(&timeout);epoll_event ev;int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout));if (nr == -1) {ERROR("epoll_wait failed: %s\n", strerror(errno));} else if (nr == 1) {((void (*)()) ev.data.ptr)();}}return 0;}init的main方法做了很多事情,我们只需要关注主要的几点,在注释1处调用property_init 来对属性进行初始化并在注释2处的调用start_property_service启动属性服务,关于属性服务,后面会讲到。

init启动流程总结分析

init启动流程总结分析

Init 启动流程Android:4.2.2Linux内核:3.1.10内核空间和应用空间是不能直接通过内存地址级别访问的,所以就需要建立某种通讯机制。

目前Linux有很多通讯机制可以在用户空间和内核空间之间交互,例如设备驱动文件(位于/dev目录中)、内存文件(/proc、/sys目录等)这些与内核空间交互的文件都在用户空间,所以在Linux内核装载完,需要首先建立这些文件所在的目录。

而完成这些工作的程序就是本文要介绍的init。

Init 是一个命令行程序。

其主要工作之一就是建立这些与内核空间交互的文件所在的目录。

当Linux内核加载完后,要做的第一件事就是调用init程序,也就是说,init是用户空间执行的第一个程序。

在分析init的核心代码之前,还需要初步了解init除了建立一些目录外,还做了如下的工作1. 初始化属性2. 处理配置文件的命令(主要是init.rc文件),包括处理各种Action。

3. 性能分析(使用bootchart工具)。

4. 无限循环执行command(启动其他的进程)。

尽管init完成的工作不算很多,不过代码还是非常复杂的。

Init程序并不是由一个源代码文件组成的,而是由一组源代码文件的目标文件链接而成的。

这些文件位于如下的目录。

<Android源代码本目录>/system/core/init其中init.c是init的主文件,现在打开该文件,看看其中的内容。

由于init是命令行程序,所以分析init.c首先应从main函数开始,现在好到main函数,代码如下:int main(int argc, char **argv){int fd_count = 0;struct pollfd ufds[4];char *tmpdev;char* debuggable;char tmp[32];int property_set_fd_init = 0;int signal_fd_init = 0;int keychord_fd_init = 0;bool is_charger = false;// 启动ueventdif (!strcmp(basename(argv[0]), "ueventd"))return ueventd_main(argc, argv);// 启动watchdogdif (!strcmp(basename(argv[0]), "watchdogd"))return watchdogd_main(argc, argv);/* clear the umask */umask(0);// 下面的代码开始建立各种用户空间的目录,如/dev、/proc、/sys等// 为rootfs创建并挂在启动所需的文件目录mkdir("/dev", 0755);mkdir("/proc", 0755);mkdir("/sys", 0755);mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");mkdir("/dev/pts", 0755);mkdir("/dev/socket", 0755);mount("devpts", "/dev/pts", "devpts", 0, NULL);mount("proc", "/proc", "proc", 0, NULL);mount("sysfs", "/sys", "sysfs", 0, NULL);/* 检测/dev/.booting文件是否可读写和创建 */close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000));// 创建/dev/null 节点,需要在后面的程序中看到打印信息的话,需要屏蔽掉这个函数open_devnull_stdio();// log初始化// klog_init()用于初始化log,通过其实现可以看出log被打印到/dev/__kmsg__文件中。

关于python中__init__方法理解

关于python中__init__方法理解

关于python中__init__⽅法理解在理解__init__⽅法之前,我们需要搞明⽩,什么时候才需要⽤到的这个⽅法什么是__init__?__init__⽅法在python中是类的初始化,通俗来讲,就是每次只要你去创建⼀个类的实例对象的时候,这个对象就会有初始化相关的属性什么时候需要去定义__init__?在我们构建的类的时候,可以看看这个属性或者这个参数,后⾯的每个⽅法都需要⽤到,如果是,那就需要__init__,例如我们定义logging类的时候,需要定义⽇志格式,输出级别。

这些其实我们在开始的时候就定义好,然后其他⽅法直接去⽤就可以了,那这个时候,我们就需要⽤到__init__,再抽象出来,⽐如⼯⼚现在需要制造⼀批红⾊铅笔,那我是直接在⽣产前,把颜⾊直接灌注到材料⾥⾯,还是先⽣产⼀个没有颜⾊的铅笔,然后再多⼀道⼯序刷上红⾊油漆,最终得到⼀个红⾊铅笔呢?很明显是,在⽣产前直接灌注对应的红⾊颜料到机器,这样只要启动按钮,⽣产出来的就是红⾊铅笔是不是很⽅便,在结合__init__,这个时候,我就在__init__⽅法⾥⾯定义颜⾊为红⾊,那么每次创建铅笔的实例对象的时候,这个铅笔就是红⾊。

这个就是__init__再来⼀个代码⼤家来看看1. 不⽤init()⽅法定义类定义⼀个矩形的类,⽬的是求周长和⾯积。

class Rectangle(): def getPeri(self,a,b): return (a + b)*2 def getArea(self,a,b): return a*brect = Rectangle()print(rect.getPeri(3,4))print(rect.getArea(3,4))得到的结果是:14 12从上例中可以看到,我们在类中并没有定义init()⽅法,但是也能够得到类似的要求,结果返回了矩形实例rect的周长及⾯积。

但是,我定义了⼀个矩形,按理来说它的属性应该是它的长、宽。

hilog 使用案例

hilog 使用案例

hilog 使用案例以下使用hilog的案例:首先,需要指定要查询的日志类型。

hilog提供了四种日志类型,包括app、core、kmsg和init。

在这个例子中,将查询app类型的日志。

然后,可以使用阻塞式实时查询来查看日志。

阻塞式实时查询会阻塞当前线程,直到有新的日志产生。

在这个例子中,将使用阻塞式实时查询来查看app类型的日志。

另外,还可以使用非阻塞式实时查询来查看日志。

非阻塞式实时查询不会阻塞当前线程,而是通过回调函数来接收新的日志。

在这个例子中,将使用非阻塞式实时查询来查看app类型的日志。

最后,还可以使用标签来过滤日志。

标签可以用于标识调用所在的类或者业务行为。

在这个例子中,将使用标签来过滤app类型的日志。

以下是一个使用hilog的Python代码示例:python复制代码import hilog# 指定要查询的日志类型为app类型hilog.init_logger('app')# 使用阻塞式实时查询查看app类型的日志for log inhilog.Hilog.instance().query_logs('app',block=True):print(log)# 使用非阻塞式实时查询查看app类型的日志def callback(log):print(log)hilog.Hilog.instance().add_callback('app', callback)# 使用标签过滤app类型的日志for log inhilog.Hilog.instance().query_logs('app',tag='my_tag'):print(log)在这个例子中,首先使用hilog.init_logger()函数指定要查询的日志类型为app类型。

然后,使用hilog.Hilog.instance().query_logs()函数来查询app类型的日志。

logrus日志自定义格式操作

logrus日志自定义格式操作

logrus⽇志⾃定义格式操作由于最近开始做⼀些go写的外围程序,因此开始关注go的⽇志,毕竟⾃带的logger模块功能较少。

简单看了⼀些资料以后最开始使⽤seelog,性能感觉也不错,可以通过配置⽂件做很多额外处理。

但是由于协程的使⽤,需要⽇志标明协程号来⽅便⽇志查询请求应答。

在⼀番尝试以后仍然没有解决,只能看看有没有其他⽇志库备选,因此选择了logrus(github上同类星星最多)其实⼀开始看介绍时就看见过logrus这个库,但是之所以没有⼀开始考虑它,是因为许多介绍都说它⽆法显⽰⽂件名和⾏号。

不过时代是发展的,现在的logrus版本已经⽀持该设置。

1)设置⾏号log.SetReportCaller(true)log.WithFields(log.Fields{"animal": "walrus"}).Info("A walrus appears")time="2020-03-29T15:58:09+08:00" level=info msg="A walrus appears" func=main.main file="F:/workspace/go/src/test/main.go:12" animal=walrus设置⾏号通过SetRportCaller实现,但是发现⼀个问题默认的设置file是全路径的,这样实际在⽇志中输出的话,⽇志会有很多⽆⽤数据,针对于我⾃⼰的需求仅为需要提⽰go⽂件名以及⾏号和goid即可。

2)⾃定义格式logrus提供了SetFormatter可以设置格式,logrus⾃带的格式为(JSONFormatter,TextFormatter)func (s *LogFormatter) Format(entry *log.Entry) ([]byte, error) {timestamp := //⽇期格式实现entry.Caller //调⽤者信息entry.Data //withfiled⽅式传⼊的数据msg := ⾃⼰想要的格式输出内容return []byte(msg), nil}func main() {log.SetFormatter(new(LogFormatter)) //注册⾃定义格式}⾃定义格式可选取的素材是log.Entry中提供的,具体了解需要⾃⾏查看源码,这⾥仅简单介绍。

androidlogd原理及实现

androidlogd原理及实现

androidlogd原理及实现⼀、logd介绍logd 是Android L版本提出来的概念,其作⽤是保存Android运⾏期间的log(⽇志)。

在Android L之前,log由kernel的ring buffer 保存,在Android L之后,log保存在⽤户空间。

1) logd进程启动系统启动到init函数时会解析init.rc⽂件,启动logd进程和logd-reinit(重新初始化logd)进程,init.rc⽂件中的相关内容如下:onload_persist_props_actionload_persist_propsstart logdstart logd-reinit在system/core/logd中的logd.rc⽂件中,启动logdservice和logd-reinit service,具体内容如下:service logd /system/bin/logdsocket logd stream 0666logd logdsocket logdr seqpacket0666 logd logdsocket logdw dgram 0222logd logdgroup root system readprocwritepid/dev/cpuset/system-background/tasksservice logd-reinit /system/bin/logd --reinitoneshotdisabledwritepid/dev/cpuset/system-background/tasks注:logd-reinit只会执⾏⼀次,logd和logd-reinit都会调⽤system/core/logd/main.cpp中的main函数,但logd-reinit通过netlink给logd进程发送reinit命令后就会退出。

2) logd 实现log管理主要原理是:上层应⽤(Android层)通过调⽤Log/Slog/Rlog中的v/d⽅法打印log,最终log会通过netlink传递给logd,logd会将log保存在内存中(由C++中的list容器管理,后续会介绍),logcat等log获取⼯具同样通过netlink⽅式从logd获取log。

golang日志框架之logrus的使用

golang日志框架之logrus的使用

golang⽇志框架之logrus的使⽤golang⽇志库golang标准库的⽇志框架⾮常简单,仅仅提供了print,panic和fatal三个函数对于更精细的⽇志级别、⽇志⽂件分割以及⽇志分发等⽅⾯并没有提供⽀持。

所以催⽣了很多第三⽅的⽇志库,但是在golang的世界⾥,没有⼀个⽇志库像slf4j那样在Java中具有绝对统治地位。

golang中,流⾏的⽇志框架包括logrus、zap、zerolog、seelog等。

logrus是⽬前Github上star数量最多的⽇志库,⽬前(2018.08,下同)star数量为8119,fork数为1031。

logrus功能强⼤,性能⾼效,⽽且具有⾼度灵活性,提供了⾃定义插件的功能。

很多开源项⽬,如docker,prometheus等,都是⽤了logrus来记录其⽇志。

zap是Uber推出的⼀个快速、结构化的分级⽇志库。

具有强⼤的ad-hoc分析功能,并且具有灵活的仪表盘。

zap⽬前在GitHub上的star数量约为4.3k。

seelog提供了灵活的异步调度、格式化和过滤功能。

⽬前在GitHub上也有约1.1k。

logrus特性logrus具有以下特性:完全兼容golang标准库⽇志模块:logrus拥有六种⽇志级别:debug、info、warn、error、fatal和panic,这是golang标准库⽇志模块的API的超集。

如果您的项⽬使⽤标准库⽇志模块,完全可以以最低的代价迁移到logrus上。

可扩展的Hook机制:允许使⽤者通过hook的⽅式将⽇志分发到任意地⽅,如本地⽂件系统、标准输出、logstash、elasticsearch或者mq 等,或者通过hook定义⽇志内容和格式等。

可选的⽇志输出格式:logrus内置了两种⽇志格式,JSONFormatter和TextFormatter,如果这两个格式不满⾜需求,可以⾃⼰动⼿实现接⼝Formatter,来定义⾃⼰的⽇志格式。

Android-根文件系统启动过程

Android-根文件系统启动过程
在系统初始化时,Android将分配一个共享内存区来存储的属性。这些是由“init”守护进程完成的,其源代码位于: device/system/init。“init”守护进程将启动一个属性服务。属性服务在“init”守护进程中运行。每一个客户端想要设置属性时,必须连接属性服务,再向其发送信息。属性服务将会在共享内存区中修改和创建属性。任何客户端想获得属性信息,可以从共享内存直接读取。这提高了读取性能。
客户端应用程序可以调用libcutils中的API函数以GET/SET属性信息。libcutils的源代码位于:device/libs/cutils。API函数是:
int property_get(const char *key, char *value, const char *default_value);
signal_recv_fd (信號機制建立)
(20) 執行所有触发标识为early-boot的action
(21) 執行所有触发标识为boot的action
(22)基于當前property狀態,執行所有触发标识为property的action
(23)注冊輪詢事件:
- device_fd
- property_set_fd
属性“ ctrl.start ”和“ ctrl.stop ”是用来启动和停止服务。每一项服务必须在/init.rc中定义.系统启动时,与init守护进程将解析init.rc和启动属性服务。一旦收到设置“ ctrl.start ”属性的请求,属性服务将使用该属性值作为服务名找到该服务,启动该服务。这项服务的启动结果将会放入“
- 如果device_fd的revents為POLLIN,調用handle_device_fd
- 如果property_fd的revents為POLLIN,調用handle_property_set_fd
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Total videomode count = 45
16bit 4/3 VIDEOMODES:
640 * 480 - ok
800 * 600 - ok
1024 * 768 - ok
1152 * 864 - ok
1280 * 960 - ok
VideoModes count = 5
AirXonix Version 1.42 (3-Apr-2005)
****** ENGINE INITIALISATION PROTOCOL ********
Sun Aug 09 20:32:10 2009
==== SYSTEM INFORMATION ====
Total phys.memory = 2012442624
640 * 480 - ok
800 * 600 - ok
1024 * 768 - ok
1152 * 864 - ok
1280 * 960 - ok
VideoModes count = 5
Sorting VideoModes:
640 * 480
800 * 600
SubSysID = -2086399933
Revision = 162
WHQLLevel = 0
Video Memory :
Total = 0
Free = 0
Video Memory for textures:
Total = 526176255
Free = 523173887
VideoModes count = 5
Sorting VideoModes:
640 * 480
800 * 600
1024 * 768
1152 * 864
1280 * 960
-----------------Device number = 2 --------------
1024 * 768
1152 * 864
1280 * 960
--------------------------
Useful device count = 3
======= END OF ENUMERATING ========
==== START DIALOG =====
Hardware device type
Total videomode count = 45
16bit 4/3 VIDEOMODES:
640 * 480 - ok
800 * 600 - ok
1024 * 768 - ok
1152 * 864 - ok
1280 * 960 - ok
Sorting VideoModes:
640 * 480
800 * 600
1024 * 768
1152 * 864
1280 * 960
-----------------Device number = 1 --------------
主显示器驱动程序 \ Microsoft Direct3D Hardware acceleration through Direct3D HAL
主显示器驱动程序 \ Microsoft Direct3D Hardware Transform and Lighting acceleration capable device
Hardware device type
Total videomode count = 45
16bit 4/3 VIDEOMODES:
Vendor id : AuthenticAMD
Processor id : x86 Family 15 Model 107 Stepping 2
Vendor id : AuthenticAMD
---------------------------
Init D3DX - ok.
========== ENUMERATING ==========
Processor family = 15
Processor model = 11
Processor freq = 2271129
-- Registry information --
DirectX version : 4.09.00.0904
Processor id : x86 Family 15 Model 107 Stepping 2
m0
==== EXIT GAME =====
==== SHUTDOUN =====
Release txr surfaces
Release DD objects
Release DirectSound objects
D3DX Uninitialize
Release resources
Setting primary buffer format - ok
- first type initialisation successful -
==== START GAME =====
m1
m2
m3
m4
m5
m6
m7
m8
m9
m10
m11
m12
m13
m14
m15
Get D3DCAPS
Blending supported
Creating Vertex Buffer - OK
Setting Render States
Creating Texture Surfaces - OK
Creating Buf.Texture Surfaces - OK
Avail phys.memory = 1392095232
Total page file = -297263104
Avail page file = -865935360
Number of processors = 2
VendorID = AuthenticAMD
Processor type = 0
Total device count = 3
-----------------Device number = 0 --------------
主显示器驱动程序 \ Microsoft Direct3D RGB Software Emulation
Software device type
DestroyWindow
deactivating
==== EXIT ====
Selected parametrs:
Device number = 1
Device index = 1
xRes = 800
yRes = 600
bMipmap = 1
bWait = 1
bHQ = 1
bHTxrRes = 1
bHardware = 1
bSound = 1
Creating main window - ok.
--- DIRECT SOUND INITIALISATION ---
Creating DS object - ok
Trying first type of initialisation
Setting writeprimary coop.level - ok
Creating primary sound buffer - ok
Init StaticMemorySystem - ok.
Prepare wave resources
Prepare bmp resources
Prepare arif.mas.
====== CREATING D3DX CONTEXT =======
Hardware Mode
Creating context 16 bpp, 16 bz, 1 back-buff - OK
Getting Interfaces
Selected Device Info:
Driver = nv4_disp.dll
Description = nForce 630a
VendorID = 4318
DeviceID = 982
相关文档
最新文档