init 订阅
init是Linux系统操作中不可缺少的程序之一。所谓的init进程,它是一个由内核启动的用户级进程。内核会在过去曾使用过init的几个地方查找它,它的正确位置(对Linux系统来说)是/sbin/init。如果内核找不到init,它就会试着运行/bin/sh,如果运行失败,系统的启动也会失败。内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。所以init始终是第一个进程(其进程编号始终为1)。 展开全文
init是Linux系统操作中不可缺少的程序之一。所谓的init进程,它是一个由内核启动的用户级进程。内核会在过去曾使用过init的几个地方查找它,它的正确位置(对Linux系统来说)是/sbin/init。如果内核找不到init,它就会试着运行/bin/sh,如果运行失败,系统的启动也会失败。内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。所以init始终是第一个进程(其进程编号始终为1)。
信息
外文名
init
属    于
Linux系统操作中不可缺少的程序
进    程
一个由内核启动的用户级进程
正确位置
是/sbin/init
init运行级别
那么,到底什么是运行级呢?简单的说,运行级就是操作系统当前正在运行的功能级别。这个级别从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)
收起全文
精华内容
下载资源
问答
  • Android系统init进程启动及init.rc全解析

    万次阅读 多人点赞 2017-11-23 16:14:40
    system/core/init/init.c文件main函数中parse_config_file(init.rc)读取并解析init.rc文件内容。将service信息放置到system/core/init/init_parser.cpp的service_list中 system/core/init/init.c文

    这是一篇用心写的博客,也希望大家用心看并帮忙找到文章的改进之处,谢谢;

    服务启动机制

    1. system/core/init/init.c文件main函数中parse_config_file(init.rc)读取并解析init.rc文件内容。将service信息放置到system/core/init/init_parser.cpp的service_list中
    2. system/core/init/init.c文件main函数继续执行restart_servie_if_needed(…) -> service_start(…) -> Execve(…)建立service进程;

    为了让大伙看得更明白,上个图先《总体启动框架图》:
    这里写图片描述

    init.rc 简介

    目前Linux有很多通讯机制可以在用户空间和内核空间之间交互,例如设备驱动文件(位于/dev目录中)、内存文件(/proc、/sys目录等)。了解Linux的同学都应该知道Linux的重要特征之一就是一切都是以文件的形式存在的,例如,一个设备通常与一个或多个设备文件对应。这些与内核空间交互的文件都在用户空间,所以在Linux内核装载完,需要首先建立这些文件所在的目录。而完成这些工作的程序就是本文要介绍的init。Init是一个命令行程序。其主要工作之一就是建立这些与内核空间交互的文件所在的目录。当Linux内核加载完后,要做的第一件事就是调用init程序,也就是说,init是用户空间执行的第一个程序。

    尽管init完成的工作不算很多,不过代码还是非常复杂的。Init程序并不是由一个源代码文件组成的,而是由一组源代码文件的目标文件链接而成的。这些文件位于如下的目录。

    需要明白的是,这些init.rc只是语法文件,并不是程序,真正的入口则是上面提到的system/core/init/init.c
    因为init.c文件比较大,在文章的第二部分我会简要的通过main函数分析init启动流程;

    init.rc有两个,分别位于:
    ./system/core/rootdir/init.rc
    ./bootable/recovery/etc/init.rc
    从目录上大致可以猜测,这两个init.rc使用场景不一样,一个是刷机用到的,也就是进入recorvery模式,一个是正常启动用到的;我们这里重点分析的是上面那个,也是init.c关联的那个;

    init.rc语法结构解析

    要了解init.rc是怎么解析的,我们需要先看看说明文档,说明文档在,当然也可以看下热心网友的中文对照版本
    init.rc位于/bootable/recovery/etc/init.rc

    Android初始化语言包含了四种类型的声明:
    Actions(行为)、Commands(命令)、Services(服务)和Options(选项)

    所有这些都是以行为单位的,各种记号由空格来隔开。
    C语言风格的反斜杠号可用于在记号间插入空格。
    双引号也可用于防止字符串被空格分割成多个记号。
    行末的反斜杠用于折行,注释行以井号(#)开头(允许以空格开头)。

    需要注意的是,这个只是一个语法文件,就像一个xml文件一样,没有执行顺序的,解析器通过读这个文件获取想要的数据,包括service,action等

    Actions和Services声明一个新的分组Section。所有的命令或选项都属于最近声明的分组。位于第一个分组之前的命令或选项将会被忽略。
    Actions和Services有唯一的名字。如果有重名的情况,第二个申明的将会被作为错误忽略。

    Actions

    Actions(行为)是一系列命令的开始
    Actions代表一些Action.Action代表一组命令(Commands),Actions都有一个trigger(触发器),该触发器决定了何时执行这个Action,即在什么情况下才能执行该Action中的定义命令.当一些条件满足触发器的条件时,该Action中定义的命令会被添加到要执行命令队列的尾部(如果这组命令已经在队列中,则不会再次添加).

    队列中的每一个action都被依次提取出,而这个action中的每个command(命令)在一个Action从队列移除时,该Action定义的命令会依次被执行.

    Action的格式如下:

    on <trgger> [&& <trigger>]*
       <command1>
       <command2>
       <command3>
       ...
    

    on后面跟着一个触发器,当trigger被触发时,command1,command2,command3,会依次执行,直到下一个Action或下一个Service。

    简单来说,Actions就是Android在启动时定义的一个启动脚本,当条件满足时,会执行该脚本,脚本里都是一些命令commands,不同的脚本用on来区分。

    ###Triggers(触发器)
    trigger即我们上面所说的触发器,本质上是一个字符串,能够匹配某种包含该字符串的事件.
    trigger又被细分为事件触发器(event trigger)和属性触发器(property trigger).
    Triggers(触发器)是一个用于匹配特定事件类型的字符串,用于使Actions发生。

    事件触发器可由"trigger"命令或初始化过程中通过QueueEventTrigger()触发,通常是一些事先定义的简单字符串,例如:boot,late-init
    属性触发器是当指定属性的变量值变成指定值时触发,其格式为property:=*

    一个Action可以有多个属性触发器,但是最多有一个事件触发器.下面我们看两个例子:

    on boot && property:a=b
    

    该Action只有在boot事件发生时,并且属性a和b相等的情况下才会被触发.

    on property:a=b && property:c=d
    

    该Action会在以下三种情况被触发:

    • 在启动时,如果属性a的值等于b并且属性c的值等于d
    • 在属性c的值已经是d的情况下,属性a的值被更新为b
    • 在属性a的值已经是b的情况下,属性c的值被更新为d

    当前AIL中常用的有以下几种事件触发器:

    类型						说明
    -------------------------------------------------
    boot					init.rc被装载后触发
    device-added-<path>		指定设备被添加时触发
    device-removed-<path>	指定设备被移除时触发
    service-exited-<name>	在特定服务(service)退出时触发
    early-init				初始化之前触发
    late-init				初始化之后触发
    init					初始化时触发(在 /init.conf (启动配置文件)被装载之后)
    

    Init的触发是由init.c里的函数action_for_each_trigger来决定的(在main函数中被调用)。

    Services

    Services(服务)是一个程序,以 service开头,由init进程启动,一般运行于另外一个init的子进程,所以启动service前需要判断对应的可执行文件是否存在。init生成的子进程,定义在rc文件,其中每一个service,在启动时会通过fork方式生成子进程。Services(服务)的形式如下:

    service <name> <pathname> [ <argument> ]*
        <option>
        <option>
        ...
    

    其中:

    • name:服务名
    • pathname:当前服务对应的程序位置
    • option:当前服务设置的选项
    • argument 可选参数

    init.rc文件详解

    为了方便理解,我把整个init.rc解析一边,便于大家了解整个流程;如果想要了解recovery下的init语法解析,参考这篇文章《recovery下的init.rc语法解析》
    代码量比较大,如果觉得看起来费劲,可以挑绿色部分看;

    # Copyright (C) 2012 The Android Open Source Project
    #
    # IMPORTANT: Do not create world writable files or directories.
    # This is a common source of Android security bugs.
    #
    
    "【import <filename>一个init配置文件,扩展当前配置。】"
    import /init.environ.rc
    import /init.usb.rc
    import /init.${ro.hardware}.rc
    import /init.${ro.zygote}.rc
    import /init.trace.rc
    
    "【触发条件early-init,在early-init阶段调用以下行】"
    on early-init
        # Set init and its forked children's oom_adj.
        write /proc/1/oom_score_adj -1000
    	"【打开路径为<path>的一个文件,并写入一个或多个字符串】"
        # Apply strict SELinux checking of PROT_EXEC on mmap/mprotect calls.
        write /sys/fs/selinux/checkreqprot 0
    
        # Set the security context for the init process.
        # This should occur before anything else (e.g. ueventd) is started.
        "【这段脚本的意思是init进程启动之后就马上调用函数setcon将自己的安全上下文设置为“u:r:init:s0”,即将init进程的domain指定为init。】"
        setcon u:r:init:s0
    
        # Set the security context of /adb_keys if present.
        "【恢复指定文件到file_contexts配置中指定的安全上线文环境】"
        restorecon /adb_keys
    
    	"【执行start ueventd的命令。ueventd是一个service后面有定义】 "
        start ueventd
    
    	"【mkdir <path> [mode] [owner] [group]   //创建一个目录<path>,可以选择性地指定mode、owner以及group。如果没有指定,默认的权限为755,并属于root用户和root组。】"
        # create mountpoints
        mkdir /mnt 0775 root system
    
    on init
    	"【设置系统时钟的基准,比如0代表GMT,即以格林尼治时间为准】"
        sysclktz 0
    
    "【设置kernel日志等级】"
    loglevel 6 ####
        write /proc/bootprof "INIT: on init start" ####
    	
    	"【symlink <target> <path>    //创建一个指向<path>的软连接<target>。】"
        # Backward compatibility
        symlink /system/etc /etc
        symlink /sys/kernel/debug /d
    
        # Right now vendor lives on the same filesystem as system,
        # but someday that may change.
        symlink /system/vendor /vendor
    
    	"【创建一个目录<path>,可以选择性地指定mode、owner以及group。】"
        # Create cgroup mount point for cpu accounting
        mkdir /acct
        mount cgroup none /acct cpuacct
        mkdir /acct/uid
    
    	"【mount <type> <device> <dir> [ <mountoption> ]   //在目录<dir>挂载指定的设备。<device> 可以是以 mtd@name 的形式指定一个mtd块设备。<mountoption>包括 ro、rw、remount、noatime、 ...】"
        # Create cgroup mount point for memory
        mount tmpfs none /sys/fs/cgroup mode=0750,uid=0,gid=1000
        mkdir /sys/fs/cgroup/memory 0750 root system
        mount cgroup none /sys/fs/cgroup/memory memory
        write /sys/fs/cgroup/memory/memory.move_charge_at_immigrate 1
        "【chown <owner> <group> <path>   //改变文件的所有者和组。】"
        
        "【后面的一些行因为类似,就省略了】"
        .....
    
    # Healthd can trigger a full boot from charger mode by signaling this
    # property when the power button is held.
    on property:sys.boot_from_charger_mode=1
    	"【停止指定类别服务类下的所有已运行的服务】"
        class_stop charger
        "【触发一个事件,将该action排在某个action之后(用于Action排队)】"
        trigger late-init
    
    # Load properties from /system/ + /factory after fs mount.
    on load_all_props_action
    	"【从/system,/vendor加载属性。默认包含在init.rc】"
        load_all_props
    
    # Indicate to fw loaders that the relevant mounts are up.
    on firmware_mounts_complete
    	"【删除指定路径下的文件】"
        rm /dev/.booting
    
    # Mount filesystems and start core system services.
    on late-init
    	"【触发一个事件。用于将一个action与另一个 action排列。】"
        trigger early-fs
        trigger fs
        trigger post-fs
        trigger post-fs-data
    
        # Load properties from /system/ + /factory after fs mount. Place
        # this in another action so that the load will be scheduled after the prior
        # issued fs triggers have completed.
        trigger load_all_props_action
    
        # Remove a file to wake up anything waiting for firmware.
        trigger firmware_mounts_complete
    
        trigger early-boot
        trigger boot
    
    
    on post-fs
    	...
        "【一些创造目录,建立链接,更改权限的操作,这里省略】"
    
    on post-fs-data
    	...
    	"【一些创造目录,建立链接,更改权限的操作,这里省略】"
    
    	"【恢复指定文件到file_contexts配置中指定的安全上线文环境】"
        restorecon /data/mediaserver
    
    	"【将系统属性<name>的值设置为<value>,即以键值对的方式设置系统属性】"
        # Reload policy from /data/security if present.
        setprop selinux.reload_policy 1
    
    	"【以递归的方式恢复指定目录到file_contexts配置中指定的安全上下文中】"
        # Set SELinux security contexts on upgrade or policy update.
        restorecon_recursive /data
    
        # If there is no fs-post-data action in the init.<device>.rc file, you
        # must uncomment this line, otherwise encrypted filesystems
        # won't work.
        # Set indication (checked by vold) that we have finished this action
        #setprop vold.post_fs_data_done 1
    
    on boot
    	"【初始化网络】"
        # basic network init
        ifup lo
        "【设置主机名为localhost】"
        hostname localhost
        "【设置域名localdomain】"
        domainname localdomain
    
    	"【设置资源限制】"
        # set RLIMIT_NICE to allow priorities from 19 to -20
        setrlimit 13 40 40
    
    	"【这里省略了一些chmod,chown,等操作,不多解释】"
       ...
       
    
        # Define default initial receive window size in segments.
        setprop net.tcp.default_init_rwnd 60
    	
    	"【重启core服务】"
        class_start core
    
    on nonencrypted
        class_start main
        class_start late_start
    
    on property:vold.decrypt=trigger_default_encryption
        start defaultcrypto
    
    on property:vold.decrypt=trigger_encryption
        start surfaceflinger
        start encrypt
    
    on property:sys.init_log_level=*
        loglevel ${sys.init_log_level}
    
    on charger
        class_start charger
    
    on property:vold.decrypt=trigger_reset_main
        class_reset main
    
    on property:vold.decrypt=trigger_load_persist_props
        load_persist_props
    
    on property:vold.decrypt=trigger_post_fs_data
        trigger post-fs-data
    
    on property:vold.decrypt=trigger_restart_min_framework
        class_start main
    
    on property:vold.decrypt=trigger_restart_framework
        class_start main
        class_start late_start
    
    on property:vold.decrypt=trigger_shutdown_framework
        class_reset late_start
        class_reset main
    
    on property:sys.powerctl=*
        powerctl ${sys.powerctl}
    
    # system server cannot write to /proc/sys files,
    # and chown/chmod does not work for /proc/sys/ entries.
    # So proxy writes through init.
    on property:sys.sysctl.extra_free_kbytes=*
        write /proc/sys/vm/extra_free_kbytes ${sys.sysctl.extra_free_kbytes}
    
    # "tcp_default_init_rwnd" Is too long!
    on property:sys.sysctl.tcp_def_init_rwnd=*
        write /proc/sys/net/ipv4/tcp_default_init_rwnd ${sys.sysctl.tcp_def_init_rwnd}
    
    "【守护进程】"
    ## Daemon processes to be run by init.
    ##
    service ueventd /sbin/ueventd
        class core
        critical
        seclabel u:r:ueventd:s0
    
    "【日志服务进程】"
    service logd /system/bin/logd
        class core
        socket logd stream 0666 logd logd
        socket logdr seqpacket 0666 logd logd
        socket logdw dgram 0222 logd logd
        seclabel u:r:logd:s0
    
    "【Healthd是android4.4之后提出来的一种中介模型,该模型向下监听来自底层的电池事件,向上传递电池数据信息给Framework层的BatteryService用以计算电池电量相关状态信息】"
    service healthd /sbin/healthd
        class core
        critical
        seclabel u:r:healthd:s0
    
    "【控制台进程】"
    service console /system/bin/sh
    	"【为当前service设定一个类别.相同类别的服务将会同时启动或者停止,默认类名是default】"
        class core
        "【服务需要一个控制台】"
        console
        "【服务不会自动启动,必须通过服务名显式启动】"
        disabled
        "【在执行此服务之前切换用户名,当前默认的是root.自Android M开始,即使它要求linux capabilities,也应该使用该选项.很明显,为了获得该功能,进程需要以root用户运行】"
        user shell
        seclabel u:r:shell:s0
    
    on property:ro.debuggable=1
        start console
    
    # adbd is controlled via property triggers in init.<platform>.usb.rc
    service adbd /sbin/adbd --root_seclabel=u:r:su:s0
        class core
        "【创建一个unix域下的socket,其被命名/dev/socket/<name>. 并将其文件描述符fd返回给服务进程.其中,type必须为dgram,stream或者seqpacke,user和group默认是0.seclabel是该socket的SELLinux的安全上下文环境,默认是当前service的上下文环境,通过seclabel指定】"
        socket adbd stream 660 system system
        disabled
        seclabel u:r:adbd:s0
    
    # adbd on at boot in emulator
    on property:ro.kernel.qemu=1
        start adbd
    
    "【内存管理服务,内存不够释放内存】"
    service lmkd /system/bin/lmkd
        class core
        critical
        socket lmkd seqpacket 0660 system system
    
    "【ServiceManager是一个守护进程,它维护着系统服务和客户端的binder通信。
    在Android系统中用到最多的通信机制就是Binder,Binder主要由Client、Server、ServiceManager和Binder驱动程序组成。其中Client、Service和ServiceManager运行在用户空间,而Binder驱动程序运行在内核空间。核心组件就是Binder驱动程序了,而ServiceManager提供辅助管理的功能,无论是Client还是Service进行通信前首先要和ServiceManager取得联系。而ServiceManager是一个守护进程,负责管理Server并向Client提供查询Server的功能。】"
    service servicemanager /system/bin/servicemanager
        class core
        user system
        group system
        critical
        onrestart restart healthd
        "【servicemanager 服务启动时会重启zygote服务】"
        onrestart restart zygote
        onrestart restart media
        onrestart restart surfaceflinger
        onrestart restart drm
    
    "【Vold是Volume Daemon的缩写,它是Android平台中外部存储系统的管控中心,是管理和控制Android平台外部存储设备的后台进程】"
    service vold /system/bin/vold
        class core
        socket vold stream 0660 root mount
        ioprio be 2
    
    "【Netd是Android系统中专门负责网络管理和控制的后台daemon程序】"
    service netd /system/bin/netd
        class main
        socket netd stream 0660 root system
        socket dnsproxyd stream 0660 root inet
        socket mdns stream 0660 root system
        socket fwmarkd stream 0660 root inet
    
    "【debuggerd是一个daemon进程,在系统启动时随着init进程启动。主要负责将进程运行时的信息dump到文件或者控制台中】"
    service debuggerd /system/bin/debuggerd
        class main
    
    service debuggerd64 /system/bin/debuggerd64
        class main
    
    "【Android RIL (Radio Interface Layer)提供了Telephony服务和Radio硬件之间的抽象层】"
    # for using TK init.modem.rc rild-daemon setting
    #service ril-daemon /system/bin/rild
    #    class main
    #    socket rild stream 660 root radio
    #    socket rild-debug stream 660 radio system
    #    user root
    #    group radio cache inet misc audio log
    
    "【提供系统 范围内的surface composer功能,它能够将各种应用 程序的2D、3D surface进行组合。】"
    service surfaceflinger /system/bin/surfaceflinger
        class core
        user system
        group graphics drmrpc
        onrestart restart zygote
    
    "【DRM可以直接访问DRM clients的硬件。DRM驱动用来处理DMA,内存管理,资源锁以及安全硬件访问。为了同时支持多个3D应用,3D图形卡硬件必须作为一个共享资源,因此需要锁来提供互斥访问。DMA传输和AGP接口用来发送图形操作的buffers到显卡硬件,因此要防止客户端越权访问显卡硬件。】"
    #make sure drm server has rights to read and write sdcard ####
    service drm /system/bin/drmserver
        class main
        user drm
        # group drm system inet drmrpc ####
        group drm system inet drmrpc sdcard_r ####
    
    "【媒体服务,无需多说】"
    service media /system/bin/mediaserver
        class main
        user root ####
    #   google default ####
    #   user media    ####
        group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm media sdcard_r system net_bt_stack ####
    #   google default ####
    #   group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm ####
    
        ioprio rt 4
    
    "【设备加密相关服务】"
    # One shot invocation to deal with encrypted volume.
    service defaultcrypto /system/bin/vdc --wait cryptfs mountdefaultencrypted
        disabled
        "【当服务退出时,不重启该服务】"
        oneshot
        # vold will set vold.decrypt to trigger_restart_framework (default
        # encryption) or trigger_restart_min_framework (other encryption)
    
    # One shot invocation to encrypt unencrypted volumes
    service encrypt /system/bin/vdc --wait cryptfs enablecrypto inplace default
        disabled
        oneshot
        # vold will set vold.decrypt to trigger_restart_framework (default
        # encryption)
    
    "【开机动画服务】"
    service bootanim /system/bin/bootanimation
        class core
        user graphics
    #    group graphics audio ####
        group graphics media audio ####
        disabled
        oneshot
    
    "【在Android系统中,PackageManagerService用于管理系统中的所有安装包信息及应用程序的安装卸载,但是应用程序的安装与卸载并非PackageManagerService来完成,而是通过PackageManagerService来访问installd服务来执行程序包的安装与卸载的。】"
    service installd /system/bin/installd
        class main
        socket installd stream 600 system system
    
    service flash_recovery /system/bin/install-recovery.sh
        class main
        seclabel u:r:install_recovery:s0
        oneshot
    
    "【vpn相关的服务】"
    service racoon /system/bin/racoon
        class main
        socket racoon stream 600 system system
        # IKE uses UDP port 500. Racoon will setuid to vpn after binding the port.
        group vpn net_admin inet
        disabled
        oneshot
    
    "【android中有mtpd命令可以连接vpn】"
    service mtpd /system/bin/mtpd
        class main
        socket mtpd stream 600 system system
        user vpn
        group vpn net_admin inet net_raw
        disabled
        oneshot
    
    service keystore /system/bin/keystore /data/misc/keystore
        class main
        user keystore
        group keystore drmrpc
    
    "【可以用dumpstate 获取设备的各种信息】"
    service dumpstate /system/bin/dumpstate -s
        class main
        socket dumpstate stream 0660 shell log
        disabled
        oneshot
    
    "【mdnsd 是多播 DNS 和 DNS 服务发现的守护程序。】"
    service mdnsd /system/bin/mdnsd
        class main
        user mdnsr
        group inet net_raw
        socket mdnsd stream 0660 mdnsr inet
        disabled
        oneshot
    
    "【触发关机流程继续往下走】"
    service pre-recovery /system/bin/uncrypt
        class main
        disabled
        "【当服务退出时,不重启该服务】"
        oneshot
    
    

    init.c全解析

    接下来我们具体分析以下这个main函数的执行过程;可能比较长,大家耐心看一下:

     
    int main( int argc, char **argv )
    {
    	#创 建一些linux根文件系统中的目录
    	mkdir( "/dev", 0755 );
    	mkdir( "/proc", 0755 );
    	mkdir( "/sys", 0755 );
    
    	mount( "tmpfs", "/dev", "tmpfs", 0, "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 );
    	#init的 标准输入,标准输出,标准错误文件描述符定向到__null__,意味着没有输入和输出,它的输入和输出全部写入到Log中
    	open_devnull_stdio();
    	#初始化 log 写入init进 信息
    	log_init();
    	#读取并 且解析init.rc文件(这个文件在根目录下)
    	parse_config_file( "/init.rc" );
    	#取得硬件 为打印我们的设备名fs100
    	get_hardware_name();
    	snprintf( tmp, sizeof(tmp), "/init.%s.rc", hardware );
        #读取并 且解析硬件相关的init脚本文件,
    	parse_config_file( tmp );
    	#触发在init脚本文件中名字为early-init的action,并且执行其commands,其实是: on early-init
    	action_for_each_trigger( "early-init", action_add_queue_tail );
    	drain_action_queue();
    	#初始化动态设备管理,设备文件有变化时反应给内核,后面具体解释
    	device_fd = device_init(); # 初 始 化 设 备 管 理 务
    	#加载启动动画,如果动画打开失败,则在屏幕上打印: A N D R O I D字样。
    	if ( load_565rle_image( INIT_IMAGE_FILE ) )
    	{
    		fd = open( "/dev/tty0", O_WRONLY );
    		if ( fd >= 0 )
    		{
    			const char *msg;
    			msg = "\n"
    			      "\n"
    			      "\n"
    			      879         "\n"
    			      "\n"
    			      "\n"
    			      "\n" /* console is 40 cols x 30 lines */
    			      "\n"
    			      "\n"
    			      "\n"
    			      "\n"
    			      "\n"
    			      "\n"
    			      "\n"
    			      /* "             A N D R O I D ";开机动画 */
    			      write( fd, msg, strlen( msg ) );
    			close( fd );
    		}
    	}
    
    	#触发 在init脚本文件中名字为init的action,并且执行其commands,其实是:on init
    	action_for_each_trigger( "init", action_add_queue_tail );
    	drain_action_queue();
    	#启动系统属性服务: system property service
    	property_set_fd = start_property_service();
    	#创建socket用来处理孤儿进程信号
    	if ( socketpair( AF_UNIX, SOCK_STREAM, 0, s ) == 0 )
    	{
    		signal_fd	= s[0];
    		signal_recv_fd	= s[1];
    		fcntl( s[0], F_SETFD, FD_CLOEXEC );
    		fcntl( s[0], F_SETFL, O_NONBLOCK );
    		fcntl( s[1], F_SETFD, FD_CLOEXEC );
    		fcntl( s[1], F_SETFL, O_NONBLOCK );
    	}
    	#触发 在init脚本文件中名字为early-boot和boot的action,并且执行其commands,其实是:on early-boot和on boot
    	action_for_each_trigger( "early-boot", action_add_queue_tail );
    	action_for_each_trigger( "boot", action_add_queue_tail );
    	drain_action_queue();
    	#启动所有属性变化触发命令,其实是: on property:ro.xx.xx=xx
    	queue_all_property_triggers();
    	drain_action_queue();
    	#进入 死循环()
    	for (;; )
    	{
    	#启 动所有init脚本中声明的service,
    	#如 :266 service servicemanager /system/bin/servicemanager
    	#user system
    	#critical
    	#onrestart restart zygote
    	#onrestart restart media
    	restart_processes();
    	#多路监听设备管理,子进程运行状态,属性服务
    		nr = poll( ufds, fd_count, timeout );
    		if ( nr <= 0 )
    			continue;
    		if ( ufds[2].revents == POLLIN )
    		{
    			read( signal_recv_fd, tmp, sizeof(tmp) );
    			while ( !wait_for_one_process( 0 ) )
    				;
    			continue;
    		}
    
    		if ( ufds[0].revents == POLLIN )
    			handle_device_fd( device_fd );
    
    		if ( ufds[1].revents == POLLIN )
    			handle_property_set_fd( property_set_fd );
    		if ( ufds[3].revents == POLLIN )
    			handle_keychord( keychord_fd );
    	}
    
    	return(0);
    }
    
    
    展开全文
  • Git init

    万次阅读 2020-02-14 23:51:09
    git init 命令及用法

    描述:

    git init命令创建一个空的Git仓库或重新初始化一个现有仓库。
    该命令创建一个空的Git仓库 - 基本上是创建一个具有objects,refs/head,refs/tags和模板文件的.git目录。 还创建了引用主分支的HEAD初始的一个HEAD文件。

    常用命令:

    • 当前目录创建仓库
      git init
    • 指定目录创建仓库
      git inti <dir>
    展开全文
  • 鸿蒙OS开源代码精要解读之——init

    万次阅读 多人点赞 2020-09-25 09:34:26
    鸿蒙OS开源代码精要解读之——init 作者介绍: 中科创达OpenHarmony研究组 说明: 中科创达OpenHarmony研究组第一时间对https://codechina.csdn.net/openharmony上开源的代码进行了详尽的代码研读和学习。为此,...

    鸿蒙OS开源代码精要解读之——init

    作者介绍

    中科创达OpenHarmony研究组

    说明

      中科创达OpenHarmony研究组第一时间对https://codechina.csdn.net/openharmony上开源的代码进行了详尽的代码研读和学习。为此,我们打算编写一系列篇幅中等,内容精炼的源码分析文章来引领大家更进一步的走进鸿蒙OS。随着对代码的了解,广大开发者想亲自动手参与的意愿和信心也会随之增强——这也是鸿蒙OS开源的意义所在。

    本篇内容摘要

    本篇以OpenHarmony中ipcamera_hi3518ev300为编译目标,介绍init进程的相关代码。

    写在前面的话

    我们对OpenHarmony的代码进行了一个简单粗略的统计。除去所有的third_party代码(即OpenHarmony使用的第三方开源库),其他剩余的代码中,以.c、.h文件为统计入口,总有效代码行数(不含注释、空行等,统计工具为tSourceCounter)为325627行。其中,归属kernel目录下的总有效代码行数为74150行。整个OpenHarmony中,kernel部分占比为22.8%左右,代码量上占大头的还在于kernel之上的、我们称之为Framework的部分。根据我们在Android系统上多年的摸索和经验,Framework恰恰是Android OS的精髓。所以,以OpenHarmony目前才20多万行的Framework代码量来看,感兴趣的开发者在这块参与共建、献策献力的机会非常大。

    1.  OpenHarmony源码的下载和编译

    先介绍代码的下载和编译。我们研究组用得是ubuntu 19.10的主机环境。

    1.1  源码下载

    按照codechina.csdn官网的源码下载指南:https://codechina.csdn.net/openharmony/docs/-/blob/master/get-code/%E6%BA%90%E7%A0%81%E8%8E%B7%E5%8F%96.md

    我们使用的是第四种方式“获取方式4:从代码仓库获取”。执行这一节中的几个命令,即可得到整个源码仓库。

    1.2  编译源码

    我们选择的编译目标是“Hi3518解决方案”,其编译后的输出目录名为ipcamera_hi3518ev300。ipcamera_hi3518ev300是一个基于海思的ip摄像头设备。相关的介绍文档入口在https://codechina.csdn.net/openharmony/docs/-/blob/master/quick-start/%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83-2.md

    注意,编译不同的解决方案需要建立对应的编译环境。对hi3518来说,开发者需要按照上述链接里的“搭建环境”来下载和配置。

    一切就绪后,在源码根目录下执行 python build.py。如果不带参数的话,它会提醒你指定编译目标,截图如下:

    图1  python build.py不带参数的执行结果

    这次,我们通过python build.py ipcamera_hi3518ev300即可编译“Hi3518解决方案”。编译耗时10几分钟。

    注意,编译过程中可能出现找不到<valgrind/valgrind.h>的错误。这是因为目前我们下载的代码中没有包含valgrind的头文件。开发者可以手动将/usr/include/valgrind目录拷贝到prebuilts/lite/sysroot/usr/include下即可(仅限Ubuntu平台,需提前安装好valgrind工具)。

    1.3  OpenHarmony编译相关小知识介绍

    OpenHarmony源码编译系统使用了google开发的gn工具以及ninjia。这二者结合起来比传统的makefile编译系要高效,尤其适合大系统的并行编译。对开发者而言,如果要参与OpenHarmony的开发,需要对gn的语法有些了解。本文仅做一些最基本的介绍:

    1. 使用gn工具的话,开发者将编译规则写在名为BUILD.gn文件中。和Makefile一样,gn文件有自己的语法规则,属于领域语言(Domain Specific Language,DSL)。gn语法不难,但编译规则本身有很多内容,所以一下子要掌握全部内容也不容易。
    2. gn支持自定义模板函数,可放在名为.gni的文件中。OpenHarmony中最常见到的gn模板文件为./build/lite/config/component/lite_component.gni。.gn文件中通过import可导入gni模板文件。OpenHarmony定义了lite_component、lite_library等模板函数。
    3. gn中,可执行文件的编译函数入口为exectuable("文件名"),共享库的编译规则函数为shared_library("文件名")。所以,如果要搜索某个文件对应的编译规则,可以先搜索所有的BUILD.gn文件,然后grep executable。以下是我们grep所有的executable的结果截图。

    图2  grep BUILD.gn中executable的结果示意

    通过这种方式,我们能很快定位到比如init对应的代码在什么地方。

    最后,我们再简单介绍下OpenHarmony编译系统中和底层OS有关的一个条件编译控制变量ohos_kernel_type。目前,该变量有四个取值,分别为"liteos_a"、"liteos_m"、"liteos_riscv"和"linux":

    1. "liteos_a"和"linux"经常做为一组进行判断。liteos_a实际对应的是Cortex-A系列,其性能相对较高,可以跑Linux系统。
    2. "liteos_m"和"liteos_riscv"往往是一组的。liteos_m对应的是Cortex-M系列,liteos_riscv是Riscv芯片的表示,二者可能都是针对性能一般,功耗较低的设备。

    ohos_kernel_type的取值由build/lite/product/解决方案名.json文件中的product字段决定。例如,我们选择的ipcamera_hi3518ev300的配置文件内容截图如下,它的kernel字段值为"liteos_a"。

    图3  build/lite/product/ ipcamera_hi3518ev300.json配置文件示意图

     编译完成后,所有编译生成物都在out/ipcamera_hi3518ev300目录下。

    2 init源码精要解析

    init是Linux系统上的第一个应用进程,是其它进程的源头。对ipcamera_hi3518ev300来说,它的编译产物中也有一个init进程。

    在上面提到的out/ipcamera_hi3518ev300目录下,有一个rootfs.tar文件。这个文件里就是设备上根文件系统的内容。打开其中的/rootfs/bin目录,可以看到此次编译的可执行程序如下截图所示:

    图4  out/ipcamera_hi3518ev300/rootfs.tar/bin内容示意

    借助图2里提到的办法,我们可以定位到init对应的代码路径为base/startup/services/init_lite/。其内容如下图所示:

    图5  init_lite源码文件示意图

    main.c是整个init的入口。我们简单看一下它的代码,如下所示。

    图6  init_lite/main.c

    init main函数非常精简,非常符合"lite"轻量简便的风格。当然,也不排除未来init的代码会越来越复杂。我们在AOSP上观察到的情况就是一个例子——AOSP里现在的init的相关代码非常复杂)。

    我们对InitReadCfg比较感兴趣,这个函数内部将读取/etc/init.cfg文件。这个文件在图4中提到的rootfs.tar中可以找到,下图是其内容的示意:

    图7  rootfs.tar/etc/init.cfg

    init.cfg本质上是一个json格式的文件。它包括一个名为"jobs"的数组和一个名为"services"的数组。

    1. 对"jobs"来说:内部分别包含"pre-init"、"init"和"post-init"三个元素。从上面的截图中可以看出,这三个元素对应的就是设置挂载一些设备、设置好路径,启动服务等工作。
    2. 对"services"来说:它包含一组服务的定义。所谓的服务,就是系统里的关键进程。可以猜测到,init将根据service的配置来启动对应的服务程序,并设置它的uid、gid、进程优先级和权限等。

    如果开发者对Android系统有一定了解的话,会发现OpenHarmony和AOSP在init的工作流程上有着相似的设计思路。不过,对OpenHarmony目标设备来说,使用json格式无疑是比较简单且方便的。

    最后,我们再看一下init的另外一个重要职能——服务进程状况监控。init.cfg中的那些服务属于系统关键进程。运行过程中如果它们出现异常导致进程退出,需要有个办法将它们重新启动以保证业务连续性。

    这个功能的实现就是利用Linux系统的SIGCHILD信号。init在SignalInitModule中监听了该信号并设置了对应的信号处理函数——SigHandler。SigHandler函数的具体处理过程则比此处说得要更复杂一点。现在,这部分内容就留给读者们自行探索了!!

    展开全文
  • 系统:ubuntu 16.04 + ROS kinetic google chrome 与终端都可以科学上网 1. 问题 按照 ros/installation在ubuntu ...$ sudo rosdep init $ rosdep update 出现以下错误: ERROR: cannot download default sources ...

    解决方案:终极解决方案来啦!!!

    首先要感谢 weixin_42817528,是他的留言让这个在我心中一直悬而未决的问题终于有了近完美的解答!然后,就是要感谢蓝鲸ROS机器人论坛的网友xiaoqiang。

    为了方便大家,现将解决方案移于此。

    #打开hosts文件
    sudo gedit /etc/hosts
    #在文件末尾添加
    151.101.84.133  raw.githubusercontent.com
    #保存后退出再尝试
    

    好完美啊!!!

    以下内容已经没有价值了,不用往下看。但还是不舍得删,留个足迹吧!


    系统:ubuntu 16.04 + ROS kinetic
    google chrome 与终端都可以xxxx

    1. 问题

    按照 ros/installation在ubuntu 16.04上安装ros kinetic,在执行以下命令时

    $ sudo rosdep init
    $ rosdep update
    

    出现以下错误:

    ERROR: cannot download default sources list from:
    https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/sources.list.d/20-default.list
    Website may be down.
    

    简要分析:我将https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/sources.list.d/20-default.list复制到浏览器地址栏打开,能够进入。开始我只能浏览器访问xx,终端ping不通xx。所以,开始我认为问题出现在终端不能xxxx上。后来,终于使终端能够访问谷歌,发现问题仍没有解决。于是总结,我的问题并不是xxxx引起的。注意后面解决方案三需要xxxx。

    2. 解决

    将问题放到网上搜了一下,相关的社区给出一些解决方法,可是这些方法对我无效。本篇将所有别人已经说了可行的解决方案与本人自己解决的方案都列出。该问题虽然现象一样,但是内部原因有很多种,大家可以按照顺序一个个试。希望有一个有用!

    2.1 解决方案一

    执行以下命令后再运行sudo rosdep init

    sudo apt-get install ca-certificates
    

    2.2 解决方案二

    执行以下命令

    sudo c_rehash /etc/ssl/certs
    sudo -E rosdep init
    

    2.3 解决方案三

    这是我自己摸索出来的解决方法,实在不行可以一试!
    首先保证你的浏览器可以xxxx,然后打开以下地址
    https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/sources.list.d/20-default.list

    打开的页面:
    在这里插入图片描述
    在本地新建对应目录/etc/ros/rosdep/sources.list.d

    $ sudo mkdir -p /etc/ros/rosdep/sources.list.d
    

    并定位到该目录:

    $ cd /etc/ros/rosdep/sources.list.d
    

    新建文件20-default.list:

    sudo gedit 20-default.list
    

    将上面打开网页中的内容复制粘贴到新建打开的文档中:

    # os-specific listings first
    yaml https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/osx-homebrew.yaml osx
    
    # generic
    yaml https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/base.yaml
    yaml https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/python.yaml
    yaml https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/ruby.yaml
    gbpdistro https://raw.githubusercontent.com/ros/rosdistro/master/releases/fuerte.yaml fuerte
    
    # newer distributions (Groovy, Hydro, ...) must not be listed anymore, they are being fetched from the rosdistro index.yaml instead
    

    并将所有raw.githubusercontent.com改为raw.github.com,得到如下最终文档:

    # os-specific listings first
    yaml https://raw.github.com/ros/rosdistro/master/rosdep/osx-homebrew.yaml osx
    
    # generic
    yaml https://raw.github.com/ros/rosdistro/master/rosdep/base.yaml
    yaml https://raw.github.com/ros/rosdistro/master/rosdep/python.yaml
    yaml https://raw.github.com/ros/rosdistro/master/rosdep/ruby.yaml
    gbpdistro https://raw.github.com/ros/rosdistro/master/releases/fuerte.yaml fuerte
    
    # newer distributions (Groovy, Hydro, ...) must not be listed anymore, they are being fetched from the rosdistro index.yaml instead
    

    保存,关闭文件。
    在终端运行:

    rosdep update
    

    得到以下信息,成功!!!
    在这里插入图片描述

    我的方式,等于人为的将文件放置到本地对应位置,这一系列过程替代sudo rosdep init

    附加步骤:
    如果经过以上过程仍不成功,更换ubuntu与ros的源:

    sudo sh -c '. /etc/lsb-release && echo "deb http://mirrors.ustc.edu.cn/ros/ubuntu/ `lsb_release -cs` main" > /etc/apt/sources.list.d/ros-latest.list'
    

    然后

    sudo apt-get update
    rosdep update
    

    2.4 解决方案四:卸载重装OLO

    部分参考ubuntu16.04 运行rosdep init 返回ERROR:cannot download default sources list from:

    这个问题的产生,根本问题出在源。
    1)如果电脑无法xxxx,那么在安装ros前,老老实实地先把源改成国内镜像源,然后再进行安装。如果出错,可以试试方法一或二。
    2)如果可以xxxx,那么可以不改源,但是在安装ros过程中一直挂着xxx,然后继续后面的安装步骤,万一出错,可以试试本博客的方法三。

    下面给出你可能需要的几个命令,如果你网络流量够的话,我建议可以卸载重装,多尝试几次;如果流量不够,我建议还是先按照本文解决方法走一遍.等下次系统被搞废后,重装ros前,根据自己实际情况(有没有xxxx),决定是不是需要将源改成国内镜像源。下面给出卸载重装步骤,卸载完之后,记得换源在装ros啊!!!.

    • 1.卸载之前安装的ros:
    $ sudo apt-get remove ros-*
    

    这一步要特别注意,确保把旧的安装文件全部删除了.以确保下次安装的ros是从新源里重新下载安装的.一个小技巧来检测安装是基于旧文件还是新源的方法:安装ros异常的快(过程中一开始就看到解析,没有看到下载),说明旧文件没被删除,安装时直接用的是旧文件.

    • 2.将源更改为国内镜像源,如中科大的源,清华大学的源等.具体源更改可参照官网.如果没有xx工具 ,不要傻乎乎的用下图1.2节中的源.请点Mirrors进入查看国内镜像源,并自行百度添加过程.

    在这里插入图片描述

    • 3.然后执行
    $ sudo apt-get update
    $ sudo apt-get install ros-kinetic-desktop-full
    $ sudo rosdep init
    $ rosdep update
    

    结语

    愿所有认真调BUG的人都能被温柔对待。小心心真的很脆很弱!!!

    展开全文
  • npm init

    千次阅读 2018-10-21 13:34:32
    npm init react-app ./my-react-app 这是用 React 初始化来创建一个项目。 如果没有初始化设定,直接使用命令: npm init 官方文档解释如下: If the initializer is omitted (by just calling npm init), init ...
  • python def __init__(self, name等多参数), def __init__(self)

    万次阅读 多人点赞 2018-10-08 20:19:22
    __init__(self) 初始化,__new__实例化方法,两者执行的顺序,先有实例,才能初始化。 之前一直对__init__(self)里面的参数很迷茫,一会这个地方看到别人这么写,一会看到别人那么写,自己也不知道,到底怎么回事,...
  • git init

    千次阅读 2017-11-06 13:49:26
    git initgit init [-q | --quiet] [--bare] [--template=] [--separate-git-dir ] [--shared[=]] [directory]$ git init # 初始化本地的仓库,会生成.git文件,此时不会加入任何文件的快照
  • init的值改成3(推荐) # 0 - 停机(千万不能把initdefault 设置为0 ) # 1 - 单用户模式 # 2 - 多用户,没有 NFS # 3 - 完全多用户模式(标准的运行级) # 4 - 没有用到 # 5 - X11 (xwindow) # 6 - 重新启动 ...
  • python中super().__init__()

    万次阅读 多人点赞 2020-03-01 21:55:12
    super().__init__() 1、子类构造函数调用super().__init__()1.1、第一个直接继承父类,可以调用name1.2、第二个继承自父类,覆盖初始化化def init,增加属性age,不能调用name属性1.3、第三个继承自父类,覆盖...
  • Linux init详解

    千次阅读 2019-05-30 20:25:22
    一、init模块 一般来说,Linux程序只能用另一个Linux程序启动。例如,登录Linux终端程序Mingetty。   但终端程序又由谁启动呢?在计算机上启动Linux时,内核装入并启动init程序。然后init程序装载硬盘和启动终端...
  • 嵌入式linux init系统(busybox init

    千次阅读 2016-05-28 15:53:50
    (一)System V init 首先我们来讨论PC上运行的Linux系统,它启动后从BIOS开始,进入bootloader,有bootloader加载内核,进入内核初始化。内核启动的最后一步就是创建一个pid为1的init进程。这是系统的第一个进程,...
  • init函数介绍

    千次阅读 2019-11-26 20:08:41
    导入一个包,先执行包里面的init函数,然后才开始执行main函数 如果程序里面就有init函数,也会在main函数之前执行的 package main import “fmt” func init ( ) { fmt.Println(“this is calc init”) } func main...
  • init方法

    千次阅读 2016-08-23 10:43:13
    init方法是在Servlet实例化之后执行的,并且只执行一次。 一.init(ServletConfig)中参数ServletConfig,代表的是配置信息。即在web.xml中配置的信息,比如:    RDSDispatchServlet RDSDispatchServlet  flex...
  • Android init 进程 init.rc init.*.rc

    千次阅读 2013-01-11 19:19:03
    1. init 进程是android 启动后由内核启动的第一用户级进程,init 进程是系统的守护进程,init进程有四个作用依次为:子进程终止处理,生成设备驱动节点,分析及运行init.rc 文件和init.*.rc 文件, 初始化属性服务。...
  • 重写父类的init方法与自定义init方法

    千次阅读 2018-07-27 14:11:17
    在为对象分配了内存空间之后要初始化对象时,我们希望初始化的结果是对象中的成员变量是有值的,但是默认情况下,init方法是不会给予这些成员变量以我们想要的值的,这个时候我们就应该重写或者自定义init方法。...
  • 安卓11 init初始化以及init.rc的解析执行过程详解

    千次阅读 热门讨论 2021-01-07 16:12:47
    最近做了一个高通平台安卓的需求,功能使得data分区在第一次启动时,自动适配emmc/ufs的实际大小,在此过程中对init的执行以及.rc文件的解析流程有了一些理解,趁热打铁!!在这里总结一下!!! 这里以mtk平台为例...
  • Init 进程详解

    千次阅读 2017-11-13 11:16:13
    Android 内核加载完成后,就会启动init进程,init进程是Android系统用户空间的第一个进程。init程序放在系统根目录下,init进程代码位于源码的目录“system/core/init”下面。下面我们来分析init进程的启动过程1. ...
  • Golang init函数

    千次阅读 2018-07-27 12:11:13
    init函数作为Go的两个保留函数之一(另一个是main函数)有很多特殊性: - init函数没有入参和返回值 - init函数不能被显式调用 - 一个package中可以包含多个init函数 - 一个go文件中可以包含多个init函数 ...
  • git init 和git --bare init的区别

    千次阅读 2018-08-31 14:11:16
    git init 和 git --bare init 的区别在于: git init 带工作区 git --bare init 是不带工作区的,只有版本库,想要看git里面的内容只能通过git clone address的方式克隆出来 而我们在初始化远程仓库时最好使用 git...
  • 官网中的示例代码 flask init-db ...那是因为init-db 已经被 flask db init 给代替了 运行 flask db init 报错 Usage: flask db init [OPTIONS] Error: Failed to find Flask application or fa...
  • linux init ramfs/init rd

    千次阅读 2013-05-06 21:44:01
    linux kernel 可以支持 init ramfs/ init rd 启动,就是在linux kernel 内核初始化完毕,切换到用户空间执行的init可以放到initrd 中,在linux menuconfig 的时候配置进去就可以将initrd 编译链接进vmlinux/zImage中...
  • SDL_Init函数

    千次阅读 2016-12-09 13:03:05
    int SDL_Init(Uint32 flags)其中,flags可以取下列值:SDL_INIT_TIMER:定时器SDL_INIT_AUDIO:音频SDL_INIT_VIDEO:视频SDL_INIT_JOYSTICK:摇杆SDL_INIT_HAPTIC:触摸屏SDL_INIT_GAMECONTROLLER:游戏控
  • git init 与git init --bare

    万次阅读 2016-09-09 15:44:19
    对于git 仓库的初始化操作,有人说用git init ,有人说用git init –bare ,那么我就来说一下这两者的区别吧。
  • 1, 如果是用系统的 init alloc方法 会先执行 initwithFrame 方法, 再执行 init方法, 自定义方法当然不会执行了. 2如果是自定义的 init方法, 会先执行 initWithFrame方法, 在执行自定义的init方法, 系统的init方法 ...
  • 成功解决TypeError: __init__() got an unexpected keyword argument 'n_iterations' 目录 解决问题 解决思路 解决方法 解决问题 TypeError: __init__() got an unexpected keyword argument 'n_...
  • Go语言_init_go的init函数

    千次阅读 2016-07-08 17:28:07
    go语言中init函数用于包(package)的初始化,该函数是go语言的一个重要特性, 有下面的特征: 1 init函数是用于程序执行前做包的初始化的函数,比如初始化包里的变量等 2 每个包可以拥有多个init函数 3 ...
  • linux init进程

    千次阅读 2016-09-11 12:36:08
    linux init进程
  • vue init webpack-simple这样的方式适合小项目,vue init webpack这样的方式适合中大型项目; 两种方式初始化Vue-Cli的项目的目录差别比较大,你可以发现使用vue init webpack这样的方式来初始化项目,默认提供了很...
  • init_task

    千次阅读 2017-01-16 17:46:07
    版权声明:本文为博主原创文章,未经博主允许不得转载。 init_task是kernel的第一个进程,0号进程,当kernel初始化完成后,它便化身为idle进程出现在我们的面前。 ... { INIT_THREAD_INFO(init_
  • SysV Init

    千次阅读 2015-10-10 11:31:52
    在提及Unix System-V Init之前,让我们想一想Windows的安全模式与Android的不同启动模式。 ①在Windows启动的时候,可以按下F8,然后选择“安全模式”启动,而安全模式启动又分为带有网络和不适用网络的安全启动...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 479,929
精华内容 191,971
关键字:

init