专栏首页QB杂货铺嵌入式linux下如何尽快播放开机音乐

嵌入式linux下如何尽快播放开机音乐

今天在考虑如何尽快启动一个应用程序,播个开机音乐什么的。

最开始的启动流程是这样的,bootloader 启动kernel,kernel跑完挂载文件系统,

然后会执行/init,而这个init 是指向busybox的一个软链接,

busybox做一些事情后,会解析/etc/inittab , 其中调用/etc/init.d/rcS 脚本,

rcS脚本里面再调用其他脚本,做一些开网络之类的功能,全部做完大概五秒多,打印出了“/ #”

此处简化下,暂且认为rcS脚本是这样的吧

#!/bin/sh 

/etc/init.d/zqbNetwork   start

这个应用程序呢,暂且叫做 zqbMusic 吧,是用来放音乐的,此处想放点开机提示音,所以我们有个音乐文件,叫kaiji.wav

调用一下 ./zqbMusic kaiji.wav 就播放了。大概一秒的音乐。

那么问题就是,如何尽快播放这个开机提示音乐。

先来个简单粗暴,直接加到rcS脚本后面,

#!/bin/sh 

/etc/init.d/zqbNetwork   start

./zqbMusic kaiji.wav

那么就在五秒多的时候,开始播放,播放完毕六秒多,打印出了"/ #",这样就比较不好了,我“/ #”之后还要启动其他应用程序呢,放音乐直接延迟了其他事情一秒多。

那么,是不是可以并行呢,考虑了一下,开网络是要时间的,放音乐也要时间,那把一个放到后台去,不要等,应该快些吧。于是改成

#!/bin/sh 

./zqbMusic kaiji.wav &

/etc/init.d/zqbNetwork   start

后面加上 & ,就是后台执行了,也就是另一个进程了。恩,今天想到并行,搜了一下才发现这么简单,加个 & 就可以了,好东西。

这么做了之后,好一些了,五秒多就可以听到声音了,打印“/ #”的时间也在五秒多(比原来慢一些,毕竟多跑了个线程抢资源)

这个时候,忍不住就要想,能不能再往前提,我干脆提到跟init并行,不改文件系统的话,这就是用户空间的极限了吧,一进来就开始播音乐

于是修改掉kernel的CMDLINE,把里面的init=/init 改成 init=/zqbinit,重新编译内核

然后就写个zqbinit.sh,大概是这样

#!/bin/sh 

./zqbMusic kaiji.wav &

exec init

搞定,丢到文件系统,烧到板子启动,结果报错了,是一个什么permission denied,具体当时没存下来,大概就是说我没有权限执行 init(实际上是busybox)

尝试了chmod 各种加权限,还是报错,暂时不知道为什么,算了干脆用C试试

于是用C写个很简单的程序,fork一个子进程,子进程去execlp调用zqbMusic,父进程则execlp 调用原本的init

大概是这样

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    pid_t pid;
    if(pid = fork()) 
    {
        execlp("./init", "init", NULL);
        exit(0);
    }
    execlp("./zqbMusic", "zqbMusic", "./kaiji.wav",NULL);
    return 0;
}

搞好Makefile,编译出zqbinit,放进去,这回可以用了

结果是,音乐在四秒多就开始播了,原本的init也能正常执行下去最终到达控制台,打印出“/ #”。

不过播放音乐这个进程,抢资源还是比较多,打印“/ #”的时间比没播音乐的情况,延迟了七八百毫秒。但总比串行执行,延迟一秒多,要好些。

而且这么看来,其他应用程序,也不是非得等到“/ #”之后调用,跟这个音乐一起并行嘛,再开个进程,也是个方法。至于到底要不要这么做,那就是另说了,毕竟进程多了切来切去也挺耗资源的。

那能不能再提前?想了下,如果在刚刚那个调用init 的父进程中,来个sleep之类的,主动让资源给zqbMusic,或者有什么小动作提一下优先级,那就是当之无愧的用户空间第一快了。

再提前?再提前就要到内核里面去了,唔,在驱动初始化完毕之后,补一个initcall,就用来放音乐,理论上似乎也是可以的,就是有点别扭。

再提前?把驱动移植到uboot中,没进内核就可以先放开机音乐了,也是一个办法。

再提前,那就太难度了,不如不要放音乐了,弄个蜂鸣器,开机滴一下(突然有种电磁炉即视感……),这个电路应该就能解决吧,绝对快。

本文链接:http://www.cnblogs.com/zqb-all/p/6012087.html

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 日志输出等级:/proc/sys/kernel/printk

    内核通过printk() 输出的信息具有日志级别,日志级别是通过在printk() 输出的字符串前加一个带尖括号的整数来控制的,如printk("<6>Hell...

    PedroQin
  • 技术公开课实录:飞桨高性能端侧推理引擎Paddle Lite技术解析

    本期是由百度飞桨资深研发工程师为大家带来飞桨高性能端侧推理引擎Paddle Lite技术解析,敬请观看。

    用户1386409
  • ring3 x32挂起进程注入原理.

    挂起进程其实就是在创建进程的时候不让其先执行.然后获取它的EIP 将它的EIP变成我们ShellCode所在的内存.进行执行.不难.

    IBinary
  • 解决 Laravel 项目跨域问题

    Access to XMLHttpRequest at 'http://youji.teavels.test/api/travels/show' from o...

    hedeqiang
  • AOSP 源码整编单编

    整编,顾名思义就是编译整个 Android 源码,最终 out 目录会生成几个重要的镜像文件,其中有 system.img、userdata.img、ramdi...

    吴小龙同學
  • [Linux] linux路由表

    路由表用于决定数据包从哪个网口发出,其主要判断依据是目标IP地址 Linux路由表其实有2个主要概念:按顺序走路由策略,在路由策略对应的路由表中匹配规则 路由策...

    陶士涵
  • 卷积神经网络学习路线(二)| 卷积层有哪些参数及常用卷积核类型盘点?

    上一篇推文介绍了卷积神经网络的组成层以及卷积层是如何在图像中起作用的,推文地址为:https://mp.weixin.qq.com/s/MxYjW02rWfRK...

    BBuf
  • 性能分析之分析决策树3与4

    当物理内存不够时,linux 触发oom,将进程杀掉;可以使用vmstat可以展现给定时间间隔的服务器的状态值,包括Linux的CPU使用率,内存使用...

    高楼Zee
  • Laravel的生命周期

    当我们在命令行终端键入php这个命令的时候,使用的就是CLI模式;当使用nginx或者其他服务器作为宿主来处理一个请求的时候,会调用php来运行,此时使用的就是...

    用户2475223
  • Linux的内核和模块

    内核通过 SCI 提供了一个应用程序接口(API)来创建一个新进程,停止进程(kill、exit),并在它们之间进行通信和同步。

    有暗香盈袖

扫码关注云+社区

领取腾讯云代金券