当前位置:首页 > Linux
  • 一起看看Ubuntu21.04有什么好玩的更新

    一起看看Ubuntu21.04有什么好玩的更新

      2021年4月22日,Ubuntu官网发布了21.04版本(Ubuntu 21.04 ‘Hirsute Hippo’),这个版本是自2006年以来的第34个版本,是一个短期版本,包括9个月的安全更新、关键修复和一些软件更新。本文会介绍新版本的新功能。 因为这是一个短期版本,如果希望直接使用稳定版本的同学可以稍微等待一下,暂时还使用Ubuntu 20.04 LTS。 想体验的同学可以直接下载并安装 Ubuntu 21.04,或者从20.10升级到 Ubuntu 21.04。这个版本的用户可以在今年晚些时候升级到 Ubuntu 21.10。 Ubuntu 21.04 ‘Hirsute Hippo’的新特性 内核Linux 5.11: 21.04版本具有 Linux 5.11内核,最新的 GNOME 3.38点发行版,与微软的活动目录更好的集成,以及对加密安装的恢复键支持。内核 5.11为处理器、图形和存储模块提供了大量的硬件支持和性能改进。 更新的应用程序 · 存档管理器3.38.2 · 计算器3.38.2 · 日历3.38.2 · 磁盘使用分析器40.0 · 磁盘实用程序40.0 · 文档扫描仪3.38.2 · 文件3.38.2 · gEdit 3.38.1 · LibreOffice 7.1.2 · Firefox 87 私人主目录 经过十多年的讨论,Ubuntu团队最终决定更改用户主目录权限。这意味着主目录不再是全局可读的。权限从755更改为750。随着Ubuntu在跨桌面,服务器和云越来越受欢迎——多个用户和少数管理员使用共享系统的可能性也越来越大。因此,在这种情况下,现在必须采取家目录私有化。 改进了深色主题和新的桌面图标扩展 将Wayland设置为默认(之前默认不会启动Wayland) 支持 Python 3.9 更多细节可以查看视频,欢迎关注 https://space.bilibili.com/239370102 下载地址: Ubuntu 21.04(64位. iso) https://releases.ubuntu.com/21.04/ubuntu-21.04-desktop-amd64.iso 下载完成后,需要copy镜像文件到一个U盘。使用像 Etcher 这样的开源工具来实现这一点。然后,在你想安装 Ubuntu 的电脑的空端口弹出 USB,选择从 USB 启动。

    时间:2021-05-03 关键词: Linux Ubuntu

  • Linus:“C++ 真是一门很烂的语言!”

    他来了他来了!Linus 带着他的“暴脾气”又来了! 近日,Rust 进入 Linux 内核的决定已正式提上议程,上周其内核开发者  Miguel Ojeda 提交了一份在 Linux 内核中添加 Rust 支持的 RFC 引起热议。 对于这件事,许多人自然想知道 Linux 之父——Linus Torvalds 的看法,毕竟这是 Linux 这么多年以来,第一次要在其内核中加入除了 C 以外的第二门编程语言。因而外媒 IT Wire 就此问题采访了 Linus。 起初他还比较“矜持”,只是比较官方地回应说 Linux 内核对 Rust 的支持还在早期阶段,等到 5.14 版本可能才会合并相关补丁。 但在知道有开发者认为“应该用 C++ 而不是 Rust”时,Linus 的“暴脾气”终于还是藏不住了。 他大笑并讽刺道:“C++ 真是一门很烂的语言!” 01 十多年来,坚持站在炮轰 C++ 第一线 如果说,Linus 对 Linux 的“爱”这三十年来从未变过,那他对 C++ 的“恨”也可以说是十几年如一日。 他早在 2007 年就开始炮轰 C++ 了。 彼时,有位名为 Dmitry Kakurin 的开发者查看了 Git 源代码发现使用的是纯 C 而非 C++ 后,他表示不可理解,于是发帖喷道:“别拿可移植性说事儿,这是胡扯(原句这里是 BS,即 bullshit)。” 好家伙,结果这句“BS”直接引爆了 Linus 的炸弹脾气。 向来以言辞犀利著称、甚至曾对 Nvidia 比中指的 Linus 自然不避讳什么脏话粗话,因此他回怼的第一句就“以其人之道还治其人之身”:“*YOU* are full of bullshit.” 报了“BS”的仇之后,Linus 接下来还把 C++ 批的一无是处:“C++ 是一门很糟糕的语言”、“很多不合格的程序员都在使用它”、“我要把喜欢用 C++ 而不是 C 来开发项目的程序员都踢出去,免得他们来搞乱我参与的项目”、“C++ 最后做出来的就是一堆可怕、难以维护的垃圾”...... 自此,Linus 与 C++ 算是彻底杠上。 这还不算完,2010 年,Linus 又在邮件列表中接连发帖吐槽 C++。依他来看,C++ 真是一门很烂的语言。他表示,无论什么时候 C++ 都不可能是最正确的选择:系统编程里直接用 C 就可以,而非系统编程里,最好选择一种有垃圾收集的语言,但 C++ 的特性除了捣乱,基本无用。 他还嘲笑 C++ 的 new 关键字很蠢,认为“C++ 就是废物,根本没啥设计,只是在 C 上面加了些渣滓而已。” 而这次采访是 Linus 时隔多年以来再次于公共场合对 C++ 进行炮轰。 02 再一次被骂“很烂”的 C++ 这次引得 Linus 再次炮轰 C++ 的是 Linux Weekly News 网站上网友 @mss 的一条评论: 解决方案很简单:用 C++ 代替 Rust。 当代码调用不安全函数时,Rust 的内存安全就得不到保证了,而目前几乎所有内核 API 都在其中。不过,你也可以轻松地使用 C++ 进行此类手动标记。 本来呢,每个人都有发言权利,尤其在现在的互联网时代,网友发言更加随心随性,哪种编程语言更好也自然是“仁者见仁,智者见智”。 可这对 Linus 来说可就不同了。他一直视 C++ 为“废物”、认为它“无用”,结果居然有人认为他们精心挑选可以进入 Linux 内核的 Rust 还比不上 C++? 因此听到这个评论的 Linus 没控制住嗤笑出声,他鄙夷说道:“C++ 根本解决不了 C 语言的问题,它只会让事情变得更糟。这真是一门很烂的语言。” 他认为,那些不喜欢 C 语言的人可以去寻找真正能给你带来价值的语言。比如具有内存安全性并可以避免 C 导致的隐患的语言,或者具有内部 GC(垃圾回收)支持并简化内存管理的语言。而这个语言明显不是 C++,因为在 Linus 看来,C++ 解决的都是错误的问题,因而那些说“用 C++ 重写内核”的人都太无知了。 与 C++ 相比,Linus 选择无条件站在 C 这一边。“当人们谈到由 C 导致的危险时,也谈到了 C 如此强大的部分原因:'它允许你高效地实现所有这些低级的东西'。”Linus 提到。此外,尽管大多数情况下 GC 对于简化编程而言都是一件挺好的事,但是它通常不是你在低级系统编程中所能做的事情。 03 网友:C++ 不是垃圾 相信大家经常可以在网上看到许多人争论有关“最佳编程语言”的话题,但随着时间的推移,越来越多新兴编程语言的崛起,大多数的人都意识到了一个事实:每种编程语言都有自身局限性,也拥有其最擅长的用武之地。 因此这次 Linus 把 C++ 骂得“一无是处”引来许多开发者的抗议。 网友@ Chuck Messenger : C++ 的伟大之处在于它“就是 C”。你能用 C 语言做一些 C++ 做不到的事情吗?据我所知没有。在每次新的迭代中,C++ 都提供了对抽象的改进支持, 我对 Rust 很感兴趣,也有可能向它迁移。但是,C++ 在任何意义上都不是“垃圾”。 网友@stikves: 他说 C++ 不适合 Linux 内核可能是对的。不过对于 C++ 这个语言......大家都知道他的看法一直比较强烈吧。 当然,C++ 也适用于其他操作系统,比如 Windows、Mac OS,甚至Android。所以这都取决于不同的项目。 这次 Linus 又把 C++ 程序员得罪了一通,不过这么多年来他的“暴脾气”也没怎么改,或许就跟编程语言一样,Linus 的“火爆”也是部分开发者的“心头好”吧!

    时间:2021-04-21 关键词: C Linux

  • 基于ARM9芯片的S3C2440和Linux操作系统设计SPI驱动程序

    基于ARM9芯片的S3C2440和Linux操作系统设计SPI驱动程序

    在嵌入式开发过程中,许多系统通常使用串口驱动来满足通信要求,但在实际应用中,使用SPI通信方式会更加高效和快捷[2]。SPI接口是一种高速、高效的串行接口技术,因而SPI设备在数据通信应用中十分方便[3]。本文基于ARM9芯片的S3C2440和Linux操作系统,设计了一种SPI驱动程序,该驱动程序功能可靠灵活、易于移植,可应用于多种嵌入式平台,实现ARM与设备之间的通信。 1硬件说明 1.1S3C2440开发平台 1.2SPI硬件模块 S3C2440具有两个SPI,每个SPI具有两个8位移位寄存器用于独立地发送和接收数据,并兼容SPIver.2.11协议,支持8位逻辑预分频,系统可用polling、中断、DMA三种方式判断SPI发送及接收状态。此SPI模块共包含以下信号线[5]: (1)SCK:数据同步时钟信号,由主设备驱动,向从设备输出,使得从设备按照同步时钟的步调来接收或发送数据。 (2)nCS(由用户指定GPIO):从设备选择信号线(SlaveSelect,SS)由主设备发出,用来选择激活某个从设备,低电平有效。 (3)MISO(SPIMISO0):主入从出信号线,表示该信号在主设备中作为输入,在从设备中作为输出。 (4)MOSI(SPIMOSI0):主出从入信号线,表示该信号在主设备中作为输出,在从设备中作为输入。 (5)/SS(nSS):多主错误检测。 2Linux下的SPI设备驱动程序设计 Linux设备驱动在Linux内核中扮演着重要的角色。它可使某些特定硬件响应一个定义良好的内部编程接口,这些接口完全隐藏了设备工作的细节。用户操作可通过一组标准化的调用来执行,这些调用在形式上完全独立于特定的驱动程序,而将这些调用映射到实际硬件设备的特有操作上,则是驱动程序的任务[6]。本设计的SPI驱动主要定义了初始化、读和写三个操作。其中初始化操作用于驱动程序第一次加载到内核运行时,对一些内核机制及存储器进行初始化。写操作负责将用户数据拷贝至内核缓冲区,控制本地主SPI发送数据至从SPI寄存器中。读操作将按照用户要求读取的字节数,连续读取本地主SPI中接收到的数据,并将其拷贝至用户空间。驱动程序将采用中断的方式通知系统SPI数据是否发送完毕,即当SPI硬件模块每发送完毕一个数据,都会通过中断线向系统发起中断,系统响应中断后,驱动程序将调用中断处理例程。 2.1SPI初始化 (1)申请中断。此驱动设计通过中断判断数据是否发送完毕,所以需要申请SPI0相关的中断,并注册相应的中断处理函数。此驱动程序的中断处理函数声明如下: staTIcirqreturn_ts3c2440_isr_spi(inTIrq,void*dev_id,structpt_regs*reg) 利用request_irq向内核申请中断号并注册中断处理函数: request_irq(IRQ_SPI0,s3c2440_isr_spi,SA_INTERRUPT,DEVICE_NAME,s3c2440_isr_spi); (2)虚拟地址映射。驱动程序可以直接通过访问内核中的虚拟地址来访问设备物理地址所对应的寄存器,对其进行操作。SPI设备的地址映射过程如下: request_mem_region(S3C2440_PA_SPI,0x30,“s3c2440-spi”); base_addr=ioremap(S3C2440_PA_SPI,0x30); 其中S3C2440_PA_SPI为SPI的物理地址(在/asm-arch/arch-s3c2440/map.h中定义),从S3C2440_PA_SPI开始分配0x30大小的内存区域,此后将其移至内核空间。 (3)相关寄存器的设置。通过配置SPI功能寄存器设置SPI工作模式。以ioremap返回的虚拟地址为基址,通过增加不同偏移量访问相应寄存器。本次设计将本地SPI设为主设备,开启SCK信号使能,设定CPOL和CPHA均为0,SPI工作在普通模式下。设置波特率预分频寄存器(SPPRE)中的分频比为8。具体设计如下: __raw_writel((S3C2440_SPCON_SMOD_INT|S3C2440_SPCON_ENSCK|S3C2440_SPCON_MSTR),s3c2440_SPCON); DPRINTK(DEVICE_NAME“SPCONiniTIalizen”); __raw_writel((S3C2440_SPPIN_ENMUL|S3C2440_SPPIN_KEEP),s3c2440_SPPIN); DPRINTK(DEVICE_NAME“SPPINiniTIalizen”); __raw_writel(0x07,s3c2440_SPPRE); DPRINTK(DEVICE_NAME“SPPREinitializen”); (4)初始化发送和接收数据缓冲区。数据缓冲区使用环形缓冲区结构,通过头尾指针的循环移动,实现对缓冲区的动态管理。其定义如下: typedefstruct { spi_bufbuf[MAX_SPI_BUF]; unsignedinthead,tail; wait_queue_head_twq; }SPI_BUF;staticSPI_BUFspi_Tx_buf;staticSPI_BUFspi_Rec_buf; 其中spi_buf表示char型,MAX_SPI_BUF为缓冲区大小,设为1024B。head、tail分别表示头尾数组下标,wq为等待队列头。此结构依靠以下宏进行管理: #defineSPI_Tx_BUF_HEAD(spi_Tx_buf.buf[spi_Tx_buf.head]) #defineSPI_Tx_BUF_TAIL(spi_Tx_buf.buf[spi_Tx_buf.tail]) #defineINCBUF(x,mod)((++(x))&((mod)-1)) 前两个宏用于引用缓冲区中的元素,最后一个宏用于对头尾下标进行前移,并保证头尾下标数值可循环变化,不发生溢出。 在初始化时,分别对接收和发送缓冲区的头尾指针进行清零操作,具体如下: spi_Tx_buf.head=spi_Tx_buf.tail=0;spi_Rec_buf.head=spi_Rec_buf.tail=0; (5)内核机制相关的数据结构初始化。本设计所使用的内核机制包括了中断上下半部的操作和睡眠等待机制,因此需要对发送、接收等待队列以及tasklet结构进行初始化,并注册tasklet处理函数。初始化过程如下: init_waitqueue_head(&(spi_Tx_buf.wq)); init_waitqueue_head(&(spi_Rec_buf.wq)); tasklet_init(&spi_tasklet,spi_tasklet_handler,data); (6)初始化相应端口。根据S3C2440外部管脚配置,将与SPI功能引脚复用的GPIO设定为SPI相应功能。具体操作如下: s3c2440_gpio_cfgpin (S3C2440_GPE11,S3C2440_GPE11_SPIMISO0); s3c2440_gpio_cfgpin (S3C2440_GPE12,S3C2440_GPE12_SPIMOSI0); s3c2440_gpio_cfgpin (S3C2440_GPE13,S3C2440_GPE13_SPICLK0); s3c2440_gpio_cfgpin (S3C2440_GPG2,S3C2440_GPG2_INP);//设置nSS s3c2440_gpio_cfgpin(S3C2440_GPB10, S3C2440_GPB10_OUTP);//设置片选信号 s3c2440_gpio_setpin(S3C2440_GPB10,1); 2.2SPI写操作 写操作主要是将上层应用部分的用户空间中的数据拷贝到内核空间中的环形缓冲区中,此后将缓冲区的数据送到SPI发送寄存器中,在SPI发送完一个数据后,系统产生中断,中断例程中的下半部将调用tasklet判断缓冲区状态。若缓冲区中有相应的空间,可以将下一数据填入SPI发送寄存器中,直至将缓冲区数据全部发送完毕。 本设计的写操作实现了环形缓冲区的动态管理,即在缓冲区删除数据、尾指针前移的情况下,允许向缓冲区添加数据,头指针前移。此设计可以使用户空间任务与内核空间的数据发送同时进行,提高了用户空间任务执行效率,并且当利用copy_from_user函数将数据从用户空间拷贝至内核空间时,数据发送仍在进行,即数据从用户空间至内核空间拷贝过程与数据发送过程并发,提高了驱动程序效率。 为了实现环形缓冲区动态管理,定义了copy_to_Tx_buf_init和copy_to_Tx_buf两个函数完成数据向缓冲区的复制操作。 (1)copy_to_Tx_buf_init函数。本函数主要用于两种情况: ①如果缓冲区为空,当有一组数据到来且此数据的大小小于缓冲区的空间大小时,直接将此数据放到缓冲区中。 ②如果发送数据的大小大于剩余缓冲区的空间,则只复制缓冲区大小的数据到缓冲区。 缓冲区满,该进程进行睡眠操作,直到缓冲区所有数据发送完毕,缓冲区再次为空,当前进程被唤醒,将此组用户数据的未发送部分复制到缓冲区,继续发送。 (2)copy_to_Tx_buf函数。此函数主要用于缓冲区正在发送且未发送完毕的情况,将新一组用户数据copy至缓冲区。首先计算缓冲区剩余空间,若剩余空间大于本组用户数据大小,则直接将用户数据全部copy至缓冲区;若剩余空间小于本组数据大小,则copy与剩余空间大小相同的用户数据至缓冲区。 写操作的具体流程如图1所示,首先用户数据从空间态转换到内核态,并设置相应的接收标志位。此后判断数据大小。若数据大于缓冲区空间,数据发生溢出,写操作结束;若没有溢出,为了保证进程间的数据,使得该进程获得自旋锁,此时判断缓冲区是否为空。根据上面两个函数的介绍,在不同情况下分别调用不同的函数,在数据写入环形缓冲区后,将数据发送到SPI的发送寄存器。当SPI发送寄存器发送数据时,环形缓冲区依旧接收数据,如果此时缓冲区为满,则释放自旋锁,并设置进程等待标志位(wait_Tx_done),将此进程休眠,直到发送寄存器中的数据发送完毕,再唤醒进程,判断数据是否全部发送完毕。若仍有数据等待发送,则调用copy_to_Tx_buf_int;若数据已全部发送完毕,则写操作结束。若缓冲区不为满,则判断数据是否发送完毕。数据全部发送完毕,发送操作结束。 2.3SPI读操作 读操作是连续读取主SPI发送到从SPI的接收缓冲区中的数据,并将其传送给用户空间。具体流程如图2所示。首先判断操作标志位spi_Rec_en,若此位为0,说明此时驱动正处于发送状态,则将发送进程等待标志位(wait_Tx_done)置1,读进程进入休眠状态即放入等待队列中,等待中断处理函数中相关发送程序唤醒。若操作标志位不为1,读进程首先获得自旋锁,判断数据大小。若数据大小不为0且不超过缓冲区大小,则按照S3C2440接收数据的要求,向SPI发送寄存器写入第一个dummy数据(0xff)。此后,将接收进程等待标志位(wait_Rec_done)置1,释放自旋锁,并将此进程加入等待队列进行休眠,直到用户要求的所有数据已发送至接收缓冲区后,由中断处理函数唤醒该进程,最后将接收区中的数据放到临时接收缓存中,以便于其他操作读取。 3SPI驱动程序测试 SPI驱动程序主要通过调用写操作,使SPI连续发送数据0x55,此后再调用SPI读操作,将MISO上的串行数据读入用户缓冲区,并与实际数据进行比较。图3为示波器测试MOSI引脚波形。图中波形1为SCK信号,ARM系统时钟为40MHz,SPI的SCK信号为系统时钟的256分频,约为156kHz;波形2为MOSI信号,SPI从低位向高位串行移位。通过波形可以看出,SPI驱动能够准确地完成读写操作,验证了其正确性。

    时间:2021-04-15 关键词: ARM arm9 SPI S3C2440 Linux

  • 详谈Linux系统之实时监控相关技术

    详谈Linux系统之实时监控相关技术

    万物互联和大数据技术的发展,让我们的生活更加活色生香,其背后离不开安全、稳定可靠的服务器系统。 这里我们主要是从系统日常行为安全的角度分享一种能满足线上部署、能够将进程或文件创建、网络连接、网络I/O、文件I/O、shell操作、数据库操作、telnet操作、http访问、系统调用(syscall)和系统资源信息等系统相关的行为信息实时采集和存储的Linux行为监控技术。 传统监控技术 现有系统行为监控的实现技术主要采用以下方法: 1.LinuxKprobes调试技术 Kprobes调试技术是一种专为Linux内核跟踪和调试而设计的特定API。Kprobes允许内核开发人员为任何内核指令以及函数入口和函数返回处理程序安装预处理程序和后处理程序,这些处理程序可以访问并更改寄存器。这样一来,内核开发者们就可以监控系统调用相关工作流程并簿记。利用Kprobes技术,内核开发人员可以在内核的绝大多数指定函数中动态地插入探测点来收集所需的调试状态信息;关于“调用了哪些系统”、“系统何时被调用”、“执行是否正确以及函数的入参和返回值是什么”等疑惑都可以轻松解决。此外,还能将这些信息屏幕输出或转储日志文件。 2.Linux内核的tracepoints(跟踪点)技术 内核的tracepoint是一种轻量级的hooks技术,使用高效的系统调用行为跟踪及相关性能计算,对系统本身的性能只有微小的时间损失和空间损失。通过注册syscall_enter_probe等定制的probe函数,在发生系统调用相关行为后,内核找到probe函数,并将参数等信息传递给probe函数。只要将probe函数中记录的相关行为信息输出,即可达到监控目的。 在现有的Linux系统行为监控工具中,采用LinuxKprobes调试技术、Linux内核的tracepoints(跟踪点)技术的工具有:strace、ftrace、tcpdump、lsof、htop、iftop、systemTap、perf…… 以上的工具通常只能作为日常内核开发调试或日常运维分析工具来使用,主要用于开发调试或问题定位等简单的信息输出。然而,这些工具存在一些使用缺陷,可以总结为以下几点: 1、仅适用于内核开发人员调试使用或是运维人员在现场开启使用,各工具特点不一,难以满足系统全面监控的需求。 2、没有提供行为数据的良好存储能力,只提供简单的输出或是日志存储。由于没有数据缓存功能,容易造成行为数据的丢包,不能很好地支撑事后数据回放或分析。 3、不能进行线上运行的实时部署,只能在事后或事中开启,无法满足运维或安全监控的自动化要求。在高吞吐、高并发的服务器上,增加了服务器运行的负担。 新型实时监控缓存技术方案 针对现有技术无法满足线上实时部署、影响服务器性能、行为数据不具备良好的存储和缓存功能等缺陷,我们给大家分享一种具备实时监控和缓存功能的技术方案。 该方案主要是采用分层结构的模型进行架构的,具体分为内核probe层、基于内存映射mmap技术的buffer层、基于本地数据库的用户态缓存层。具体结构如下图: 业务流程描述 下面通过一个具体的系统行为事件信息采集-缓存的例子,来说明这三层之间的业务流关系: 首先,当用户发起网络连接服务主机操作,在服务主机系统中将发生socketaccpet系统调用中断,服务进程陷入内核态,进入系统调用例程。 其次,通过Linux内核tracepoints机制,内核查找系统调用tracepoint的probe函数;此时,内核查到已经挂载的内核probe层的probe函数,并将相应accpet系统调用参数信息传入probe函数。 接下来,内核probe层的probe函数将传来的系统调用相关信息进行分类、序列化处理后,将相关参数信息转化为系统行为事件信息写入mmapbuffer层。 最后,用户态缓存层进程通过mmap映射技术,从mmapbuffer层读取具体的系统行为事件信息,将系统行为事件信息再次格式化为易于阅读和分析的字符串信息,并选择一种本地或分布式的缓存技术,持久化存储系统行为事件信息。 通过上述业务流程的分析,可以概括出上述三层主体功能分别为:内核probe层采集系统调用信息、mmapbuffer层转化系统行为事件信息、用户态缓存层持久化系统行为事件信息。如下图所示: 通过上文可以得知,本方案与目前现有工具或方案的主要区别在于本方案体现了以下两方面:实时性、缓存持久化。 实时性 “实时性”就是指系统操作行为(系统调用)信息能够实时感知,“零损耗”地对信息进行采集。 我们知道系统行为信息的采集是由“内核probe层”完成的,在该层中主要也是采用了Linux内核字符设备驱动技术+Linuxtracepoints机制。通过开发Linux内核字符设备驱动来驱动probe模块,在probe模块中挂载tracepoint函数,采集各系统调用的相关信息。 为了实现系统调用信息从内核probe层到用户态缓存层的“Zerocopy”高效传递,在probe层与用户态缓存层采用了Linux内核驱动与用户态进程实现地址共享的mmapbuffer技术方案。 缓存持久化 经过内核probe层采集的系统行为事件信息存放在mmapbuffer层中,为了实时高效地将这些事件信息持久化存储,本方案采用了一种开源高效的本地文件数据库引擎,该引擎占用资源少、无需安装和管理配置、数据吞吐率每秒可达上万条记录。这样轻型的持久化模块,可以通过“零损耗”的方式部署到线上服务器,而不占用服务器资源。 从mmapbuffer层中读取到系统行为事件信息,在用户态缓存层还可以根据具体业务的要求,做一些数据处理分析,如格式化、过滤等。最终存放到文件数据库中,从而实现系统行为事件信息的持久化缓存。

    时间:2021-04-15 关键词: 操作系统 监控 Linux

  • 还在敲代码? 来看看如何自动生成

    素材来源:最后一个bug 状态(State) 指的是对象在其生命周期中的一种状况,处于某个特定状态中的对象必然会满足某些条件、执行某些动作或者是等待某些事件。 事件(Event) 指的是在时间和空间上占有一定位置,并且对状态机来讲是有意义的那些事情。事件通常会引起状态的变迁,促使状态机从一种状态切换到另一种状态。 转换(Transition) 指的是两个状态之间的一种关系,表明对象将在第一个状态中执行一定的动作,并将在某个事件发生- 同时某个特定条件满足时进入第二个状态。 动作(Action) 指的是状态机中可以执行的那些原子操作,所谓原子操作指的是它们在运行的过程中不能被其他消息所中断,必须一直执行下去。 二、手工编写状态机 与其他常用的设计模式有所不同,程序员想要在自己的软件系统中加入状态机时,必须再额外编写一部分用于逻辑控制的代码,如果系统足够复杂的话,这部分代码实现和维护起来还是相当困难的。在实现有限状态机时,使用switch语句是最简单也是最直接的一种方式,其基本思路是为状态机中的每一种状态都设置一个case分支,专门用于对该状态进行控制。下面的代码示范了如何运用switch语句,来实现图1中所示的状态机: switch (state) { // 处理状态Opened的分支 case (Opened): { // 执行动作Open open(); // 检查是否有CloseDoor事件 if (closeDoor()) { // 当前状态转换为Closed changeState(Closed) } break; } // 处理状态Closed的分支 case (Closed): { // 执行动作Close close(); // 检查是否有OpenDoor事件 if (openDoor()) { // 当前状态转换为Opened changeState(Opened); } // 检查是否有LockDoor事件 if (lockDoor()) { // 当前状态转换为Locked changeState(Locked); } break; } // 处理状态Locked的分支 case (Locked): { // 执行动作Lock lock(); // 检查是否有UnlockDoor事件 if (unlockDoor()) { // 当前状态转换为Unlocked changeState(Unlocked); } break; } // 处理状态Unlocked的分支 case (Unlocked): { // 执行动作Unlock unlock(); // 检查是否有LockDoor事件 if (lockDoor()) { // 当前状态转换为Locked changeState(Locked) } // 检查是否有OpenDoor事件 if (openDoor()) { // 当前状态转换为Opened changeSate(Opened); } break; } } 使用switch语句实现的有限状态机的确能够很好地工作,但代码的可读性并不十分理想,主要原因是在实现状态之间的转换时,检查转换条件和进行状态转换都是混杂在当前状态中来完成的。例如,当城门处于Opened状态时,需要在相应的case中调用closeDoor()函数来检查是否有必要进行状态转换,如果是的话则还需要调用changeState()函数将当前状态切换到Closed。显然,如果在每种状态下都需要分别检查多个不同的转换条件,并且需要根据检查结果让状态机切换到不同的状态,那么这样的代码将是枯燥而难懂的。从代码重构的角度来讲,此时更好的做法是引入checkStateChange()和performStateChange()两个函数,专门用来对转换条件进行检查,以及激活转换时所需要执行的各种动作。这样一来,程序结构将变得更加清晰: switch (state)  { // 处理状态Opened的分支 case (Opened): { // 执行动作Open open(); // 检查是否有激发状态转换的事件产生 if (checkStateChange()) { // 对状态机的状态进行转换 performStateChange();     } break;   } // 处理状态Closed的分支 case (Closed): { // 执行动作Close close(); // 检查是否有激发状态转换的事件产生 if (checkStateChange()) { // 对状态机的状态进行转换 performStateChange();     } break;   } // 处理状态Locked的分支 case (Locked): { // 执行动作Lock lock(); // 检查是否有激发状态转换的事件产生 if (checkStateChange()) { // 对状态机的状态进行转换 performStateChange();     } break;   } // 处理状态Unlocked的分支 case (Unlocked): { // 执行动作Lock unlock(); // 检查是否有激发状态转换的事件产生 if (checkStateChange()) { // 对状态机的状态进行转换 performStateChange();     } break;   } } 但checkStateChange()和performStateChange()这两个函数本身依然会在面对很复杂的状态机时,内部逻辑变得异常臃肿,甚至可能是难以实现。 在很长一段时期内,使用switch语句一直是实现有限状态机的唯一方法,甚至像编译器这样复杂的软件系统,大部分也都直接采用这种实现方式。但之后随着状态机应用的逐渐深入,构造出来的状态机越来越复杂,这种方法也开始面临各种严峻的考验,其中最令人头痛的是如果状态机中的状态非常多,或者状态之间的转换关系异常复杂,那么简单地使用switch语句构造出来的状态机将是不可维护的。 三、自动生成状态机 为实用的软件系统编写状态机并不是一件十分轻松的事情,特别是当状态机本身比较复杂的时候尤其如此,许多有过类似经历的程序员往往将其形容为"毫无创意"的过程,因为他们需要将大量的时间与精力倾注在如何管理好状态机中的各种状态上,而不是程序本身的运行逻辑。作为一种通用的软件设计模式,各种软件系统的状态机之间肯定会或多或少地存在着一些共性,因此人们开始尝试开发一些工具来自动生成有限状态机的框架代码,而在Linux下就有一个挺不错的选择──FSME(Finite State Machine Editor)。 FSME是一个基于Qt的有限状态机工具,它能够让用户通过图形化的方式来对程序中所需要的状态机进行建模,并且还能够自动生成用C++或者Python实现的状态机框架代码。下面就以城门的状态机为例,来介绍如何利用FSME来自动生成程序中所需要的状态机代码。 3.1状态机建模 首先运行fsme命令来启动状态机编辑器,然后单击工具栏上的"New"按钮来创建一个新的状态机。FSME中用于构建状态机的基本元素一共有五种:事件(Event)、输入(Input)、输出(Output)、状态(State)和转换(Transition),在界面左边的树形列表中可以找到其中的四种。 转换建模 状态转换是整个建模过程中最重要的一个部分,它用来定义有限状态机中的一个状态是如何切换到另一个状态的。例如,当用来控制城门的状态机处于Opened状态时,如果此时有Close事件产生,那么状态机的当前状态将切换到Closed状态,这样一个完整的过程在状态机模型中可以用closeDoor这样一个转换来进行描述。 要在FSME中添加这样一个转换,首先需要在界面左边的树形列表中选择"States"下的"Opened"项,然后按下键盘上的Insert键来添加一个新的转换,接着在右下角的"Name"文本框中输入转换的名字"closeDoor",在"Condition"文本框中输入"Close"表明触发该转换的条件是事件Close的产生,在"Target"下拉框中选择"Closed"项表明该转换发生后状态机将被切换到Closed状态,最后再单击"Apply"按钮,一个新的状态转换关系就定义好了。用同样的办法可以添加状态机所需要的所有转换。 3.2 生成状态机框架 使用FSME不仅能够进行可视化的状态机建模,更重要的是它还可以根据得到的模型自动生成用C++或者Python实现的状态机框架。首先在FSME界面左边的树形列表中选择"Root"项,然后在右下角的"Name"文本框中输入状态机的名字"DoorFSM",再从"Initial State"下拉列表中选择状态"Opened"作为状态机的初始化状态。 在将状态机模型保存为door.fsm文件之后,使用下面的命令可以生成包含有状态机定义的头文件: [xiaowp@linuxgam code]$ fsmc door.fsm -d -o DoorFSM.h 进一步还可以生成包含有状态机实现的框架代码: [xiaowp@linuxgam code]$ fsmc door.fsm -d -impl DoorFSM.h -o DoorFSM.cpp 如果想对生成的状态机进行验证,只需要再手工编写一段用于测试的代码就可以了: /*  * TestFSM.cpp  * 测试生成的状态机框架  */ #include "DoorFSM.h" int main() {   DoorFSM door;   door.A(DoorFSM::Close);   door.A(DoorFSM::Lock);   door.A(DoorFSM::Unlock);   door.A(DoorFSM::Open); } 有限状态机是由事件来进行驱动的,在FSME生成的状态机框架代码中,方法A()可以被用来向状态机发送相应的事件,从而提供状态机正常运转所需要的"动力"。状态机负责在其内部维护一个事件队列,所有到达的事件都会先被放到事件队列中进行等候,从而能够保证它们将按照到达的先后顺序被依次处理。在处理每一个到达的事件时,状态机都会根据自己当前所处的状态,检查与该状态对应的转换条件是否已经被满足,如果满足的话则激活相应的状态转换过程。 使用下面的命令能够将生成的状态机框架和测试代码编译成一个可执行文件: [xiaowp@linuxgam code]$ g++ DoorFSM.cpp TestFSM.cpp -o fsm 由于之前在用fsmc命令生成状态机代码时使用了-d选项,生成的状态机框架中会包含一定的调试信息,包括状态机中每次状态转换时的激活事件、转换前的状态、所经历的转换、转换后的状态等,如下所示: [xiaowp@linuxgam code]$ ./fsm DoorFSM:event:'Close' DoorFSM:state:'Opened' DoorFSM:transition:'closeDoor' DoorFSM:new state:'Closed' DoorFSM:event:'Lock' DoorFSM:state:'Closed' DoorFSM:transition:'lockDoor' DoorFSM:new state:'Locked' DoorFSM:event:'Unlock' DoorFSM:state:'Locked' DoorFSM:transition:'unlockDoor' DoorFSM:new state:'Unlocked' DoorFSM:event:'Open' DoorFSM:state:'Unlocked' DoorFSM:transition:'openDoor' DoorFSM:new state:'Opened' 3.3 定制状态机 目前得到的状态机已经能够响应来自外部的各种事件,并适当地调整自己当前所处的状态,也就是说已经实现了状态机引擎的功能,接下来要做的就是根据应用的具体需求来进行定制,为状态机加入与软件系统本身相关的那些处理逻辑。在FSME中,与具体应用相关的操作称为输出(Output),它们实际上就是一些需要用户给出具体实现的虚函数,自动生成的状态机引擎负责在进入或者退出某个状态时调用它们。 仍然以控制城门的那个状态机为例,假设我们希望在进入每个状态时都添加一部分处理逻辑。首在FSME界面左边的树形列表选择"Outputs"项,然后按下键盘上的Insert键来添加一个新的输出,接着在右下方的"Name"文本框中输入相应的名称,再单击"Apply"按钮,一个新的输出就创建好了,如图7所示。用同样的办法可以添加状态机所需要的所有输出。 图7 添加输出 当所有的输出都定义好之后,接下来就可以为状态机中的每个状态绑定相应的输出。首先在FSME界面左侧的"States"项中选择相应的状态,然后从右下角的"Available"列表框中选择与该状态对应的输出,再单击"<"按钮将其添加到"In"列表中,如图8所示。用同样的办法可以为状态机中的所有状态设置相应的输出,同一个状态可以对应有多个输出,其中In列表中的输出会在进入该状态时被调用,而Out列表中的输出则会在退出该状态时被调用,输出调用的顺序是与其在In或者Out列表中的顺序相一致的。 图8 为状态设置输出 由于对状态机模型进行了修改,我们需要再次生成状态机的框架代码,不过这次不需要加上-d参数: [xiaowp@linuxgam code]$ fsmc door.fsm -o DoorFSM.h [xiaowp@linuxgam code]$ fsmc door.fsm -d -impl DoorFSM.h -o DoorFSM.cpp 我们在新的状态机模型中添加了enterOpend、enterClosed、enterLocked和enterUnlocked四个输出,因此生成的类DoorFSM中会包含如下几个纯虚函数: virtual void enterOpened() = 0; virtual void enterLocked() = 0; virtual void enterUnlocked() = 0; virtual void enterClosed() = 0; 显然,此时生成的状态机框架不能够再被直接编译了,我们必须从类DoorFSM派生出一个子类,并提供对这几个纯虚函数的具体实现: /*  * DoorFSMLogic.h  * 状态机控制逻辑的头文件  */ #include "DoorFSM.h" class DoorFSMLogic : public DoorFSM { protected: virtual void enterOpened(); virtual void enterLocked(); virtual void enterUnlocked(); virtual void enterClosed(); }; 正如前面所提到过的,这几个函数实际上代表的正是应用系统的处理逻辑,作为例子我们只是简单地输出一些提示信息: /*  * DoorFSMLogic.cpp  * 状态机控制逻辑的实现文件  */ #include "DoorFSMLogic.h" #include void DoorFSMLogic::enterOpened() { std::cout << "Enter Opened state." << std::endl; } void DoorFSMLogic::enterClosed() { std::cout << "Enter Closed state." << std::endl; } void DoorFSMLogic::enterLocked() { std::cout << "Enter Locked state." << std::endl; } void DoorFSMLogic::enterUnlocked() { std::cout << "Enter Unlocked state." << std::endl; } 同样,为了对生成的状态机进行验证,我们还需要手工编写一段测试代码: /*  * TestFSM.cpp  * 测试状态机逻辑  */ #include "DoorFSMLogic.h" int main() {   DoorFSMLogic door;   door.A(DoorFSM::Close);   door.A(DoorFSM::Lock);   door.A(DoorFSM::Unlock);   door.A(DoorFSM::Open); } 使用下面的命令能够将生成的状态机框架和测试代码编译成一个可执行文件: [xiaowp@linuxgam code]$ g++ DoorFSM.cpp DoorFSMLogic.cpp TestLogic.cpp -o logic 运行结果如下所示: [xiaowp@linuxgam code]$ ./logic Enter Closed state. Enter Locked state. Enter Unlocked state. Enter Opened state. 四、小结 在面向对象的软件系统中,有些对象具有非常复杂的生命周期模型,使用有限状态机是描述这类对象最好的方法。作为一种软件设计模式,有限状态机的概念虽然不算复杂,实现起来也并不困难,但它的问题是当状态机的模型复杂到一定的程度之后,会带来实现和维护上的困难。Linux下的FSME是一个可视化的有限状态机建模工具,而且支持状态机框架代码的自动生成,借助它可以更加轻松地构建基于有限状态机的应用系统。 参考资料 从Wiki百科全书 http://en.wikipedia.org/wiki/Finite_state_automaton开始,你可以了解到许多同状态机相关的计算理论知识。 状态机是UML的一个重要组成部分,Robert C. Martin在他的文章UML Tutorial: Finite State Machines中,介绍了如何使用UML语言来对状态机进行建模,你可以通过网址 http://www.objectmentor.com/resources/articles/umlfsm.pdf可以找到这一文档。 FSME是Linux下一个基于Qt的状态机建模工具,它能够自动生成状态机框架代码,并且同时支持C++和Python语言,通过网站 http://fsme.sourceforge.net/你可以了解到有关FSME的更多信息,并能够下载最新版本的FSME。 Qfsm也是一个运行在Linux下的状态机建模工具,它不仅提供了可视化的状态机编辑器,而且还能够对生成的状态机进行实时模拟,通过网站 http://qfsm.sourceforge.net/可以了解到Qfsm的更多信息。 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-04-02 关键词: 代码 Linux

  • Linux 30岁,这些年经历了什么?

    来源 | CSDN 整理 | Carol 3月19日,Linux基金会在Twitter上发布推文宣布,其小企鹅的标志“Tux”已经30周岁了,还为其设计了一系列的庆祝海报,以便大家转发分享。 虽然离Linux的生日还有一段时间,但是今年Linux基金会已经提前先帮小企鹅“Tux”过生日了。 在今年4月,Linux还会在其线上商店推出30周年纪念周边。 Tux是Linux的吉祥物,也是Linux和开源社群的象征,想必大家对这个形象不会陌生,据说英国 Linux 用户组 (British LUG) 甚至在当地的动物园认养了几只企鹅。而Tux的形象在这期间也改版过好几次: 不过,虽然推文上是祝Tux生日快乐,但实际上Tux真正确定、并对外公布是在1996年,真正30岁的是Linux(1991年诞生)。 不知不觉,Linux“出道”已经30年了,作为自由软件和开放源代码软件发展中最具代表性的例子,你对它的了解到底有多少? 今天我们就一起回首一下,Linux的起源和30年来的重要事件。 1. Linux的诞生 说到Linux,就不得不提到Linux之父——Linus Torvalds。 用美国《时代》周刊的评价来说,那就是:“有些人生来就具有统帅百万人的领导风范;另一些人则是为写出颠覆世界的软件而生。唯一一个能同时做到这两者的人,就是Linus Torvalds。” 相信大部分读者也都会觉得,这已经是一个非常高的评价了。但在Linus这句话说出来之后,《时代》周刊的评价未免显得太保守了。Linus是这样评价自己的:“我的名字叫Linus,我是你的上帝(My name is Linus,and I am your God)。” 1969年末,Linus出生在芬兰赫尔辛基,早年父母离异,Linus大部分时间是跟着母亲生活。他的外公是个统计学教授,因此家里有一台用于工作的CommodoreVIC-20计算机。这玩意儿在当时的欧洲很流行,外公经常让年幼的Linus玩这台电脑,还经常口述程序让他敲入到电脑里。 这台电脑是Linus童年最亲密的玩伴,他对这种输入-输出的游戏十分痴迷。他还用这台电脑学会了Basic语言。到了大学时他已经有了丰富的编程经验。 在这里不得不提一位同样是传奇的人物:Andrew Tanenbaum。Andrew Tanenbaum是阿姆斯特丹自由大学计算机科学系教授,由于Unix不再免费向学校提供源代码,他为了能在课堂上更好地演示操作系统的细节,决定在不查看任何Unix源代码的情况下,自行开发一套与Unix兼容的操作系统,这套系统全部代码只有12,000行,可运行在286的英特尔芯片上,取名为Minix,即Mini-Unix。 Minix发布于1987年,作为Andrew教授《操作系统:设计与实现》一书的参考范例。这个系统虽然很迷你,但凭借低廉的价格和简易的操作,在大学中大行其道,一时风头无两。 但Andrew教授当时肯定想不到,在1000多公里外的北欧,一位刚刚服完兵役的少年,被他这本719页的大部头改写了命运。这个少年正是Linus。用Linus的话说:“这本书把我推上了生命的高峰”,看了这本书以后,操作系统、Unix和C语言成为了年少的Linus心中的维纳斯、阿波罗和雅典娜。 2. 个人爱好一不小心改变了世界 1991年1月,Linus花了3500美元分期付款购买了一台杂牌组装电脑。这台电脑的内存只有4兆、CPU 33兆赫,配有一台14英寸的显示器。然后他又用16张磁盘把Minix系统装进了电脑旁。Linux的初始版本就是在这台电脑上诞生的。 刚安装完Minix系统的Linus用了一个多月的时间把这个系统的里里外外研究了一遍,发现这个系统虽好,但也存在很多缺陷,比如内核问题、文件系统问题,但最要命的是这个系统缺少一个登陆学校Unix服务器的终端。于是Linus决定抛开Minix,重新设计一个终端仿真器,也就是说他需要在硬件层面重新开发一套新系统! 两个月之后,终端仿真器完成,这是Linux操作系统的第一步。之后,Linus又开始添加磁盘驱动和文件系统。在那段时间,Linus除了参加每周三晚上的同学聚会之外,大部分时间都穿着睡衣坐在计算机前不知疲倦的敲打着键盘。 家门外彼得盖坦街的白雪融化了他不知道,现在是三月还是四月他也不知道。他的窗帘把窗户遮盖的严严实实,把阳光和外面的世界一同和自己区隔开来。 1991年9月17日,Linus把完成的新操作系统上传到了赫尔辛基工程学院的FTP 服务器上,并准备用「Freax」作为操作系统的最终代号,结果遭到了激烈的反对。要知道发布一个操作系统可是开天辟地的大事,应该用自己的名字命名才对,把Linus一改,改成Linux就顺眼多了。可Linus却担心这个名字显得自己太自恋。最终还是「民意」占了上风。 由于Linux的开放,早年参与开发的黑客都具有很高的水平,直到今天,Linux社区里内核的开发才被程序员们认为是「真正的编程」。 3. Linux 不得不知的重要节点 1991年:Linus 向全世界介绍Linux Linus Torvalds 在1991年 8 月 25 日向 Minix Usenet 新闻组发邮件告知自己正在研发操作系统的消息,他在邮件中写道:”我做这个系统只是出于我的个人爱好,不会像 GNU 那样成为 386(486) AT 克隆的那样大而专业的系统。" 1992 年:Linux 迎来首战 操作系统大师、Unix 的教育操作系统版本 Minix 的创造者 Andrew Tannenbaum 宣称 “Linux 已经过时了”,Linux 面临的第一次操作系统战争开始了。在由此引发的讨论中,Linus Torvalds 对 Linux 的愿景做了一个很有说服力的评论,直到今天,这个评论依然是正确的,“ 如果 GNU 内核(另一个创建类似 Unix 的自由操作系统的项目)在去年春天就已经准备好了,我甚至不会费心去启动我的项目。然而事实是,它没有,现在仍然没有。Linux 在现在可用的点上赢得了很大的优势。" 1993 年:Slackware Linux 发行 Linux 在早期有一些发行版,如 MCC 和 Yggdrasil Linux,但 Patrick Volkerding 的 Slackware 是第一个广泛成功的 Linux 发行版,它至今仍在更新和使用。 1993 年 :Debian Linux 诞生 Debian Linux是一个非常受欢迎的Linux社区版。即使在今天,它也依然是Mint、Ubuntu和许多其它流行Linux发行版的基础。 1994 年:红帽公司成立 Marc Ewing创建了Red Hat Linux,Bob Young收购了Ewing的公司,并将其与自己的公司合并,并成立了Red Hat,这是迄今为止最成功的Linux公司。 1995 年:首届 Linux 博览会开幕 1995 年,Linux 举行了首个博览会 Linux Expo,之后,诞生了更多的展会。今天,仅在美国就有十多个主要的地区性和全国性的 Linux 贸易展。 1996 年:KDE 诞生 这一年,Matthias Ettrich 为方便使用,创作了 Linux 第一个桌面界面,KDE。“K” 表示 “Kool” 的意思。这个名字也是 Unix 的通用桌面环境(CDE)的一个近似变换。 1996 年:SUSE Linux 发布 同样在 1996 年,在 Slackware 和红帽 Linux 合作后,欧洲顶级商用 Linux 厂商 SUSE 发布了其首款独立 Linux 发行版。如今 SUSE 依然是 Linux 和云计算领域的重要厂商。 1997 年:GNOME问世 Miguel de Icaza 和 Federico Mena 开始着手开发一个新的 Linux 桌面,GNOME 桌面。该桌面完全基于自由软件构建,GNOME 与 KDE 一起将成为 Linux 最重要的两个桌面之一。 1998 年:微软的“万圣节文件” 微软开始瞄准 Linux,早期的 Linux 和开放源代码负责人 Eric S. Raymond 透露了一份来自微软内部的万圣节文件,该文件表明微软正认真对待 Linux 所带来的市场威胁,并开始制定其反开放源代码和Linux运动。然而十年后,微软改变了自己的腔调。 Corel 发布了第一个主流 Linux 桌面。虽未成功,但它将为其他流行的 Linux 桌面发行版铺平了道路,例如后来 Ubuntu 。 1999 年:Linux 与 Windows 首次正面对决 Linux 首次在文件服务方面与 Windows NT 进行了基准测试。Linux胜出。Linux 与 Windows 服务器的操作系统大战正式开始。Linux 最终获胜。如今,Linux 在Web服务器和云空间都占据着主导位置。 2000 年:IBM 向 Linux 投资 10 亿美元 这一年,IBM 打破了与 Linux 的企业市场僵局,并向 Linux 投资 10 亿美元,事实证明,这是 IBM 迄今为止最好的投资。 2001 年:Linux 2.4 版本发布 虽然有所延迟,但 Linux 2.4 版本的到来,让 Linux 在 Solaris 和其他高端服务器操作系统方面变得更具竞争力。 2003:SCO 与 Linux 开战 SCO 是由旧的 SCO Unix 和 Caldera Linux 业务组成,但它抛弃了 Linux 的历史,起诉 IBM 和其他公司,并试图证明 Linux 是 Unix 的副本。最终以失败告终,但它的 FUD 却在相当一段时间里阻扰了Linux 的商业接受度。 2004 年:新成员 Ubuntu 来了 建立在 Debian Linux之上的 Ubuntu 正式到来,其成了非常流行的 Linux 桌面操作系统,并且也是所有云 Linux 发行版中最重要的一个。 2004 年:Linux 统治超级计算机 全球一半以上最快的计算机都运行在 Linux 之上。2017年,会是所有超级计算机。 2005 年:Linux 成功商业化 Linus Torvalds 首次出现在了《商业周刊》的封面上,打破了人们对 Linux 成为主要商业参与者的任何怀疑。广告语是什么?Linux Inc. 今天,你很难找到任何不在 Linux 上运行的大型企业。 2007 年:Android 系统诞生 包括谷歌和众多硬件厂商在内的开放手机联盟宣布推出 Android 系统。它将成为最受欢迎的移动端用户操作系统,因为它在超过 10 亿部智能手机上运行。 2008 年:股票交易系统转向 Linux 纽约证券交易所改用 Linux 作为核心操作系统,这一举措很快就被世界上许多其他主要证券交易所效仿。Linux 并没有成为大生意,Linux 本身就是大生意。 2011 年:Watson 赢了 Jeopardy IBM 的 Watson 计算机运行在 Linux 上,赢得了 Jeopardy 智力挑战,为智能专家系统订立了新的标准。 2011年:Chromebook 兴起 谷歌发布了第一台 Chromebook:CR-48。它运行着基于 Gentoo-Linux 的 ChromeOS。到 2015,Chromebook 的销售额已经超过了运行着 Windows 的笔记本。 2012 年:云运行在 Linux 上 IT 基础设施从服务器和数据中心移动到了云端,而云运行在 Linux 上。即使是在微软 Azure 上,2016 年的时候超过 1/3 的虚拟机运行在 Linux 上。 2012 年:Red Hat 营收首次达到 10 亿美金 Red Hat 成为第一家年收入达 10 亿美金的开源公司。而在 2016,它成为首家达到 20 亿美金的 Linux 公司。 2014 年:微软 “示爱” Linux 微软新任 CEO Satya Nadella 宣称,“ 微软热爱 Linux ”。随后,微软通过在云端和内部部署支持 Linux 和开源软件来证明这一点,逐渐走上拥抱开源之路。 2018 年:微软开源其专利组合 这有可能是微软有史以来支持开源的最激进举动,微软将其整个专利组合向开放发明网络(OIN)开源专利联盟的成员开放。OIN 是为 Linux 的所有专利进行辩护的非营利组织。 2019 年:微软为 Win 10 用户推出 Linux 微软紧接着为 Windows 10 用户推出了自己的原生 Linux —— Windows Subsystem for Linux 2.0。有了它,人们可以将 Linux 与 Windows 同时运行。 2019 年:IBM 收购红帽 红帽被 IBM 以 340 亿美元收购,成为有史以来最大的软件收购案。从 IBM 的这一举动不难看出Linux 如今在科技界的主导地位。 2020 年:Linux 统治云天下 现在全球云市场每年超过 1000 亿美元。其中 90% 运行在 Linux 上。即使在 Microsoft Azure 上,也有一半以上的 VM 是 Linux。 Linux用10年名扬天下,20年统治服务器。Linux的源代码完全公开,让如今的编程人员都可以加入建设、从中受益。也许正如《时代》周刊所说的,Linus是天生的领导者和开创者,Linux也成为了带领一代人走进编程世界的明灯。 在Linux 30周年之际,一起祝它生日快乐吧!

    时间:2021-03-29 关键词: Linux基金会 Linux

  • 实践 | 基于Linux的AP3216三合一整合型光感测器实验分享

    时间:2021-03-29 关键词: 光感测器 AP3216 Linux

  • 内推字节 Linux C/C++ 开发的那位同学没通过面试......

    最近同事内推了一位 Linux C/C++ 后端开发的同学到我们公司面试,我是一面的面试官,很遗憾这位工作了两年的同学面试表现不是很好。 我问了如下一些问题: “Redis 持久化机制,redis 销毁方式机制,MQ 实现原理,C++ 虚函数,hash 冲突的解决,memcached 一致性哈希,socket 函数、select/poll/epoll模型,同步互斥,异步非阻塞,回调的概念,innodb索引原理,单向图最短路径,动态规划算法。” 为了帮助更多的同学拿到满意的 offer,我整理了一下发出来,那么 Linux C/C++ 岗位一般会问哪些知识点呢? C++ 面试一般考察的内容 1. 语言基础 C++ 虚函数这是面试初、中级 C++ 职位一个概率 95% 以上的面试题。一般有以下几种问法: 1.在有继承关系的父子类中,构建和析构一个子类对象时,父子构造函数和析构函数的执行顺序分别是怎样的? 2.在有继承关系的类体系中,父类的构造函数和析构函数一定要申明为 virtual 吗?如果不申明为 virtual 会怎样? 3.什么是 C++ 多态?C++ 多态的实现原理是什么? 4.什么是虚函数?虚函数的实现原理是什么? 5.什么是虚表?虚表的内存结构布局如何?虚表的第一项(或第二项)是什么? 6.菱形继承(类 D 同时继承 B 和 C,B 和 C又继承自A)体系下,虚表在各个类中的布局如何?如果类B和类C同时有一个成员变了m,m如何在D对象的内存地址上分布的?是否会相互覆盖? 另外,时至今日,你一定要熟悉 C++11/14/17 常用的语言特性和类库,这里简单地列一下: 统一的类成员初始化语法与 std::initializer_list 注解标签(attributes) final/override/=default/=delete 语法 auto 关键字 Range-based 循环语法 结构化绑定 stl 容器新增的实用方法 std::thread 线程局部存储 thread_local 线程同步原语 std::mutex、std::condition_variable 等 原子操作类 智能指针类 std::bind/std::function C++11/14 网上的资料已经很多了,C++17 的资料不多,重头戏还是 C++11 引入的各种实用特性,这就给读者推荐一本我读过的: 《深入理解 C++11:C++11 新特性解析与应用》 《深入应用 C++11:代码优化与工程级应用》 《C++17 完全指南》 《Cpp 17 in Detail》 这里网络上也有人分享出来,下载链接: 链接: https://pan.baidu.com/s/1Af_6-bkugcTFljpIoeIk7Q 密码: mltg 建议购买正版哦。 C++11/14/17 的语法虽然很实用,但是需要一定的练习才能掌握,推荐几个学习 C++11/14/17 的开源项目: 1. filezilla filezilla 是一款开源的 FTP 软件,其源码下载地址如下: https://svn.filezilla-project.org/svn/FileZilla3/trunk 需要使用 svn 工具来下载,安装好 svn 工具后,在 svn 界面中 checkout 上述地址或者使用如下命令下载: svn co https://svn.filezilla-project.org/svn/FileZilla3/trunk filezilla 如果使用 svn 图形化工具,直接使用以下 svn 地址将源码 checkout 到指定目录即可: https://svn.filezilla-project.org/svn/FileZilla3/trunk 如果你不知道怎么下载,可以直接在“高性能服务器开发”公众号回复“获取Filezilla源码”进行下载。 2. uWebSocket 网络库 uWebSocket 是一款开源的 WebSocket 库,最新版使用了大量 C++17 的语法,美中不足的是这个库代码存在不少 bug,我在项目中使用了它,但修改了其大量的 bug,有兴趣的朋友也可以下载下来看一下: 下载地址: https://github.com/uNetworking/uWebSockets 3. TeamTalk 的 PC 端 TeamTalk 是蘑菇街开源的一款用于企业内部的即时通信工具,其下载地址是: https://github.com/balloonwj/TeamTalk/tree/master/win-client 4. 最后是我的开源 Flamingo IM https://github.com/balloonwj/flamingo balloonwj/flamingo 2. 算法与数据结构基础 说到算法和数据结构,对于社招人士和对于应届生一般是不一样的,对于大的互联网公司和一般的小的企业也是不一样的。下面根据我当面试官面试别人和找工作被别人面试经验来谈一谈。 先说考察的内容,除了一些特殊的岗位,常见的算法和数据结构面试问题有如下: 1.排序(常考的排序按频率考排序为:快速排序 > 冒泡排序 > 归并排序 > 桶排序) 一般对于对算法基础有要求的公司,如果你是应届生或者工作经验在一至三年内,以上算法如果写不出来,给面试官的影响会非常不好,甚至直接被 pass 掉。对于工作三年以上的社会人士,如果写不出来,但是能分析出其算法复杂度、最好和最坏的情况下的复杂度,说出算法大致原理,在多数面试官面前也可以过的。注意,如果你是学生,写不出来或者写的不对,基本上面试过不了。 1.二分查找 二分查找的算法尽量要求写出来。当然,大多数面试官并不会直接问你二分查找,而是结合具体的场景,例如如何求一个数的平方根,这个时候你要能想到是二分查找。我在2017年年底,面试agora时,面试官问了一个问题:如何从所有很多的ip地址中快速找个某个ip地址。 2.链表 无论是应届生还是工作年限不长的社会人士,琏表常见的操作一定要熟练写出来,如链表的查找、定位、反转、连接等等。还有一些经典的问题也经常被问到,如两个链表如何判断有环(我在2017年面试饿了么二面、上海黄金交易所一面被问过)。链表的问题一般不难,但是链表的问题存在非常多的“坑”,如很多人不注意边界检查、空链表、返回一个链表的函数应该返回链表的头指针等等。 3.队列与栈 对于应届生来说一般这一类问的比较少,但是对于社会人士尤其是中高级岗位开发,会结合相关的问题问的比较多,例如让面试者利用队列写一个多线程下的生产者和消费者程序,全面考察的多线程的资源同步与竞态问题(下文介绍多线程面试题时详细地介绍)。栈一般对于基础要求高的面试,会结合函数调用实现来问。即函数如何实现的,包括函数的调用的几种常见调用方式、参数的入栈顺序、内存栈在地址从高向低扩展、栈帧指针和栈顶指针的位置、函数内局部变量在栈中的内存分布、函数调用结束后,调用者和被调用者谁和如何清理栈等等。某年面试京东一基础部门,面试官让写从0加到100这样一个求和算法,然后写其汇编代码。 4.哈希表 哈希表是考察最多的数据结构之一。常见的问题有哈希冲突的检测、让面试者写一个哈希插入函数等等。基本上一场面试下来不考察红黑树基本上就会问哈希表,而且问题可浅可深。我印象比较深刻的是,当年面试百度广告推荐部门时,二面问的一些关于哈希表的问题。当时面试官时先问的链表,接着问的哈希冲突的解决方案,后来让写一个哈希插入算法,这里需要注意的是,你的算法中插入的元素一定要是通用元素,所以对于 C++ 或者 Java 语言,一定要使用模板这一类参数作为哈希插入算法的对象。然后,就是哈希表中多个元素冲突时,某个位置的元素使用链表往后穿成一串的方案。最终考察 linux 下 malloc(下面的ptmalloc) 函数在频繁调用造成的内存碎片问题,以及开源方案解决方案 tcmalloc 和 jemalloc。总体下来,面试官是一步步引导你深入。(有兴趣的读者可以自行搜索,网上有很多相关资料) 5.树 面试高频的树是红黑树,也有一部分是B树(B+树)。红黑树一般的问的深浅不一,大多数面试官只要能说出红黑树的概念、左旋右旋的方式、分析出查找和插入的平均算法复杂度和最好最坏时的算法复杂度,并不要写面试者写出具体代码实现。一般 C++ 面试问 stl 的map,java 面试问 TreeMap 基本上就等于开始问你红黑树了,要有心里准备。笔者曾经面试爱奇艺被问过红黑树。B树一般不会直接问,问的最多的形式是通过问 MySQL 索引实现原理(数据库知识点将在下文中讨论)。笔者面试腾讯看点部门二面被问到过。 6.图 图的问题就我个人面试从来没遇到过,不过据我某位哥哥所说,他在进三星电子之前有一道面试题就是深度优先和广度优先问题。 7.其他的一些算法 如 A*寻路、霍夫曼编码也偶尔会在某一个领域的公司的面试中被问到。 3. 编码基本功 还有一类面试题不好分类,笔者姑且将其当作是考察编码基本功,这类问题既可以考察算法也可以考察你写代码基本素养,这些素养不仅包括编码风格、计算机英语水平、调试能力等,还包括你对细节的掌握和易错点理解,如有意识地对边界条件的检查和非法值的过滤。请读者看以下的代码执行结果是什么? int atoi(const char* p); 容易疏忽的地方有如下几点: 小数点问题,如数字 0.123 和 .123 都是合法的; 正负号问题,如 +123 和 -123; 考虑如何识别第一个非法字符问题,如 123Z89,则应转换成应该 123。 4. 多线程开发基础 现如今的多核 CPU 早已经是司空见惯,而多线程编程早已经是“飞入寻常百姓家”。对于大多数桌面应用(与 Web 开发相对),尤其是像后台开发这样的岗位,且面试者是社会人员(有一定的工作经验),如果面试者不熟悉多线程编程,那么一般会被直接 pass 掉。 这里说的 “熟悉多线程编程” 到底熟悉到什么程度呢?一般包括:知道何种场合下需要新建新的线程、线程如何创建和等待、线程与进程的关系、线程局部存储(TLS 或者叫 thread local)、多线程访问资源产生竞态的原因和解决方案等等、熟练使用所在操作系统平台提供的线程同步的各种原语。 对于 C++ 开发者,你需要: 对于 Windows 开发者,你需要熟练使用 Interlock系列函数、CriticalSection、Event、Mutex、Semphore等API 函数和两个重要的函数 WaitForSingleObject、WaitForMultipleObjects。 对于 Linux 开发者,你需要熟练使用 mutex、semphore、condition_variable、read-write-lock 等操作系统API。 可以使用 C++ 实现一个简单的线程池,当然支持优先级、动态创建线程功能就更好了。 5. 数据库 数据库知识一般在大的互联网企业对应届生不做硬性要求,对于小的互联网企业或社会人士一般有一定的要求。其要求一般包括: (1)熟悉基本 SQL 操作 包括增删改查(insert、delete、update、select语句),排序 order,条件查询(where 子语句),限制查询结果数量(LIMIT语句)等 (2)稍微高级一点的 SQL 操作(如 Group by,in,join,left join,多表联合查询,别名的使用,select 子语句等) (3)索引的概念、索引的原理、索引的创建技巧 (4)数据库本身的操作,建库建表,数据的导入导出 (5)数据库用户权限控制(权限机制) (6)MySQL的两种数据库引擎的区别 (7)SQL 优化技巧 以上属于对开发的基本的数据库知识要求,你可以找一本相关入门级的数据库图书学习即可。 高级开发除了以上要求还要熟悉高可用 MySQL、主从同步、读写分离、分表分库 等技术,这些技术的细节一定要清楚,它们是你成为技术专家或者高级架构的必备知识。 我们在实际面试时,在讨论高可用服务服务方案时,很多面试者也会和我们讨论到这些技术,但是不少面试者只知道这些技术的大致思想,细节往往说不清楚,细节不会就意味着你的高可用方案无法落地,企业需要可以落地的方案。 这些技术我首推 《高性能 MySQL》 这本书,这本书高级开发者一定要通读的,另外还有 2 本非常好的图书也推荐一下:一本是 《MySQL 排错指南》, 读完这本书以后,你会对整个“数据库世界”充满了清晰的认识;另外一本是 《数据库索引设计与优化》, 这本书读起来非常舒服,尤其是对于喜欢算法和数据结构的同学来说。 网上也有同学整理分享出来,下载链接(喜欢记得买正版哦): 链接: https://pan.baidu.com/s/1mCTqrOXkpsRbEpPK-lmrVg  密码: foqu 6. 网络编程 网络编程这一块,对于应届生或者初级岗位一般只会问一些基础网络通信原理(如三次握手和四次挥手)的 socket  基础 API 的使用,客户端与服务器端网络通信的流程(回答 【客户端创建 socket -> 连接 server ->收发数据;服务器端创建 socket -> 绑定 IP 和端口号 -> 启动侦听 ->接受客户端连接 ->与客户端通信收发数据】即可)、TCP 与 UDP 的区别等等。 对于工作经验三年以内的社会人士或者一些中级面试者一般会问一些稍微重难点问题,如 select 函数的用法,非阻塞 connect 函数的写法,epoll 的水平和边缘模式、阻塞socket与非阻塞 socket 的区别、send/recv 函数的返回值情形、REUSE_ADDR 选项等等。Windows 平台可能还会问 WSAEventSelect 和 WSAAsyncSelect 函数的用法、完成端口(IOCP 模型)。 对于三年以上尤其是“号称”自己设计过服务器、看过开源网络通信库代码的面试者,面试官一般会深入问一些问题,这类问题要么是实际项目中常见的难题或者网络通信细节,根据我的经验,一般有这样一些问题: 1.nagle 算法; 2.keepalive 选项; 3.Linger 选项; 4.对于某一端出现大量 CLOSE_WAIT 或者 TIME_WAIT 如何解决; 5.通讯协议如何设计或如何解决数据包的粘包与分片问题; 6.心跳机制如何设计;(可能不会直接问问题本身,如问如何检查死链) 7.断线重连机制如何设计; 8.对 IO Multiplexing 技术的理解; 9.收发数据包正确的方式,收发缓冲区如何设计; 10.优雅关闭; 11.定时器如何设计; 12.epoll 的实现原理。 举两个例子,让读者感受一下: B 站面试曾被问的一个问题:如果 A 机器与 B 机器网络 connect 成功后从未互发过数据,此时其中一机器突然断电,则另外一台机器与断电的机器之间的网络连接处于哪种状态? 7. 内存数据库&缓存技术 时下以 NoSql key-value 为思想的内存数据库大行其道,广泛地用于各种后台项目开发。所以 熟悉一种或几种内存数据库程序已经是面试后台开发的基本要求, 而这当中以 Redis 为最典型代表,这里以 Redis 为例。 第一层面一般是对 Redis 的基础用法的考察 如考察 Redis 支持的基础数据类型、Redis的数据持久化、事务等。 第二层面不仅考察 Redis 的基础用法,还会深入到 Redis 源码层面上,如 Redis 的网络通信模型、Redis 各种数据结构的实现等等。 Redis 高可用技术、cluster、哨兵策略等。 笔者以为,无论是从找工作应付面试还是从提高技术的角度,Redis 是一个非常值得学习的开源软件,希望广大读者有意识地去了解、学习它。 另外一些像分布式、RPC、MQ 等技术和 C++ 本身关系不是很紧密,这里就不罗列了。 8. 项目经验 除了社会招聘和一些小型的企业,一般的大型互联网公司对应届生不会做过多的项目经验要求,而是希望他们算法与数据结构等基础扎实、动手实践能力强即可。对于一般的小公司,对于应届生会要求其至少熟练使用一门编程语言以及相应的开发工具,号称熟悉 Linux C++ 开发的面试者,不熟悉 GDB 调试基本上不是真正的熟悉 Linux C++ 开发;号称熟悉汇编或者反汇编,不熟悉 IDA 或者 OllyDbg,基本上也是名不符实的;号称熟悉 VC++ 开发,连 F8、F9、F10、F11、F12 等快捷键不熟悉也是难以经得住面试官的提问的。受疫情影响,很多面试都改成了线上面试,当你写算法题时如果你对开发工具不熟悉,面试官基本一下子就能看出来。 这点请大家注意。 这里给一些学历不算好,学校不是非常有名,尤其是二本以下的广大想进入 IT 行业的同学一个建议,在大学期间除了要学好计算机专业基础知识以外,一定要熟练使用一门编程语言以及相应的开发工具。 关于项目经验,许多面试者认为一定要是自己参与的项目,其实也可以来源于你学习和阅读他人源码或开源软件的源码,如果你能理解并掌握这些开源软件中的思想和技术,在面试的时候能够与面试官侃侃而谈,面试官也会非常满意的。 很多同学可能纠结大学或者研究生期间要不要跟着导师做一些项目。当然,如果这些项目是课程要求,那么你必须得参加;如果这些项目是可以选择性的,尤其是一些仅仅拿着第三方的库进行所谓的包装和加工,那么建议可以少参加一些。 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-03-29 关键词: 字节 C Linux

  • 基于ARM9芯片的S3C2440和Linux操作系统设计SPI驱动程序

    基于ARM9芯片的S3C2440和Linux操作系统设计SPI驱动程序

    在嵌入式开发过程中,许多系统通常使用串口驱动来满足通信要求,但在实际应用中,使用SPI通信方式会更加高效和快捷[2]。SPI接口是一种高速、高效的串行接口技术,因而SPI设备在数据通信应用中十分方便[3]。本文基于ARM9芯片的S3C2440和Linux操作系统,设计了一种SPI驱动程序,该驱动程序功能可靠灵活、易于移植,可应用于多种嵌入式平台,实现ARM与设备之间的通信。 1硬件说明 1.1S3C2440开发平台 1.2SPI硬件模块 S3C2440具有两个SPI,每个SPI具有两个8位移位寄存器用于独立地发送和接收数据,并兼容SPIver.2.11协议,支持8位逻辑预分频,系统可用polling、中断、DMA三种方式判断SPI发送及接收状态。此SPI模块共包含以下信号线[5]: (1)SCK:数据同步时钟信号,由主设备驱动,向从设备输出,使得从设备按照同步时钟的步调来接收或发送数据。 (2)nCS(由用户指定GPIO):从设备选择信号线(SlaveSelect,SS)由主设备发出,用来选择激活某个从设备,低电平有效。 (3)MISO(SPIMISO0):主入从出信号线,表示该信号在主设备中作为输入,在从设备中作为输出。 (4)MOSI(SPIMOSI0):主出从入信号线,表示该信号在主设备中作为输出,在从设备中作为输入。 (5)/SS(nSS):多主错误检测。 2Linux下的SPI设备驱动程序设计 Linux设备驱动在Linux内核中扮演着重要的角色。它可使某些特定硬件响应一个定义良好的内部编程接口,这些接口完全隐藏了设备工作的细节。用户操作可通过一组标准化的调用来执行,这些调用在形式上完全独立于特定的驱动程序,而将这些调用映射到实际硬件设备的特有操作上,则是驱动程序的任务[6]。本设计的SPI驱动主要定义了初始化、读和写三个操作。其中初始化操作用于驱动程序第一次加载到内核运行时,对一些内核机制及存储器进行初始化。写操作负责将用户数据拷贝至内核缓冲区,控制本地主SPI发送数据至从SPI寄存器中。读操作将按照用户要求读取的字节数,连续读取本地主SPI中接收到的数据,并将其拷贝至用户空间。驱动程序将采用中断的方式通知系统SPI数据是否发送完毕,即当SPI硬件模块每发送完毕一个数据,都会通过中断线向系统发起中断,系统响应中断后,驱动程序将调用中断处理例程。 2.1SPI初始化 (1)申请中断。此驱动设计通过中断判断数据是否发送完毕,所以需要申请SPI0相关的中断,并注册相应的中断处理函数。此驱动程序的中断处理函数声明如下: staTIcirqreturn_ts3c2440_isr_spi(inTIrq,void*dev_id,structpt_regs*reg) 利用request_irq向内核申请中断号并注册中断处理函数: request_irq(IRQ_SPI0,s3c2440_isr_spi,SA_INTERRUPT,DEVICE_NAME,s3c2440_isr_spi); (2)虚拟地址映射。驱动程序可以直接通过访问内核中的虚拟地址来访问设备物理地址所对应的寄存器,对其进行操作。SPI设备的地址映射过程如下: request_mem_region(S3C2440_PA_SPI,0x30,“s3c2440-spi”); base_addr=ioremap(S3C2440_PA_SPI,0x30); 其中S3C2440_PA_SPI为SPI的物理地址(在/asm-arch/arch-s3c2440/map.h中定义),从S3C2440_PA_SPI开始分配0x30大小的内存区域,此后将其移至内核空间。 (3)相关寄存器的设置。通过配置SPI功能寄存器设置SPI工作模式。以ioremap返回的虚拟地址为基址,通过增加不同偏移量访问相应寄存器。本次设计将本地SPI设为主设备,开启SCK信号使能,设定CPOL和CPHA均为0,SPI工作在普通模式下。设置波特率预分频寄存器(SPPRE)中的分频比为8。具体设计如下: __raw_writel((S3C2440_SPCON_SMOD_INT|S3C2440_SPCON_ENSCK|S3C2440_SPCON_MSTR),s3c2440_SPCON); DPRINTK(DEVICE_NAME“SPCONiniTIalizen”); __raw_writel((S3C2440_SPPIN_ENMUL|S3C2440_SPPIN_KEEP),s3c2440_SPPIN); DPRINTK(DEVICE_NAME“SPPINiniTIalizen”); __raw_writel(0x07,s3c2440_SPPRE); DPRINTK(DEVICE_NAME“SPPREinitializen”); (4)初始化发送和接收数据缓冲区。数据缓冲区使用环形缓冲区结构,通过头尾指针的循环移动,实现对缓冲区的动态管理。其定义如下: typedefstruct { spi_bufbuf[MAX_SPI_BUF]; unsignedinthead,tail; wait_queue_head_twq; }SPI_BUF;staticSPI_BUFspi_Tx_buf;staticSPI_BUFspi_Rec_buf; 其中spi_buf表示char型,MAX_SPI_BUF为缓冲区大小,设为1024B。head、tail分别表示头尾数组下标,wq为等待队列头。此结构依靠以下宏进行管理: #defineSPI_Tx_BUF_HEAD(spi_Tx_buf.buf[spi_Tx_buf.head]) #defineSPI_Tx_BUF_TAIL(spi_Tx_buf.buf[spi_Tx_buf.tail]) #defineINCBUF(x,mod)((++(x))&((mod)-1)) 前两个宏用于引用缓冲区中的元素,最后一个宏用于对头尾下标进行前移,并保证头尾下标数值可循环变化,不发生溢出。 在初始化时,分别对接收和发送缓冲区的头尾指针进行清零操作,具体如下: spi_Tx_buf.head=spi_Tx_buf.tail=0;spi_Rec_buf.head=spi_Rec_buf.tail=0; (5)内核机制相关的数据结构初始化。本设计所使用的内核机制包括了中断上下半部的操作和睡眠等待机制,因此需要对发送、接收等待队列以及tasklet结构进行初始化,并注册tasklet处理函数。初始化过程如下: init_waitqueue_head(&(spi_Tx_buf.wq)); init_waitqueue_head(&(spi_Rec_buf.wq)); tasklet_init(&spi_tasklet,spi_tasklet_handler,data); (6)初始化相应端口。根据S3C2440外部管脚配置,将与SPI功能引脚复用的GPIO设定为SPI相应功能。具体操作如下: s3c2440_gpio_cfgpin (S3C2440_GPE11,S3C2440_GPE11_SPIMISO0); s3c2440_gpio_cfgpin (S3C2440_GPE12,S3C2440_GPE12_SPIMOSI0); s3c2440_gpio_cfgpin (S3C2440_GPE13,S3C2440_GPE13_SPICLK0); s3c2440_gpio_cfgpin (S3C2440_GPG2,S3C2440_GPG2_INP);//设置nSS s3c2440_gpio_cfgpin(S3C2440_GPB10, S3C2440_GPB10_OUTP);//设置片选信号 s3c2440_gpio_setpin(S3C2440_GPB10,1); 2.2SPI写操作 写操作主要是将上层应用部分的用户空间中的数据拷贝到内核空间中的环形缓冲区中,此后将缓冲区的数据送到SPI发送寄存器中,在SPI发送完一个数据后,系统产生中断,中断例程中的下半部将调用tasklet判断缓冲区状态。若缓冲区中有相应的空间,可以将下一数据填入SPI发送寄存器中,直至将缓冲区数据全部发送完毕。 本设计的写操作实现了环形缓冲区的动态管理,即在缓冲区删除数据、尾指针前移的情况下,允许向缓冲区添加数据,头指针前移。此设计可以使用户空间任务与内核空间的数据发送同时进行,提高了用户空间任务执行效率,并且当利用copy_from_user函数将数据从用户空间拷贝至内核空间时,数据发送仍在进行,即数据从用户空间至内核空间拷贝过程与数据发送过程并发,提高了驱动程序效率。 为了实现环形缓冲区动态管理,定义了copy_to_Tx_buf_init和copy_to_Tx_buf两个函数完成数据向缓冲区的复制操作。 (1)copy_to_Tx_buf_init函数。本函数主要用于两种情况: ①如果缓冲区为空,当有一组数据到来且此数据的大小小于缓冲区的空间大小时,直接将此数据放到缓冲区中。 ②如果发送数据的大小大于剩余缓冲区的空间,则只复制缓冲区大小的数据到缓冲区。 缓冲区满,该进程进行睡眠操作,直到缓冲区所有数据发送完毕,缓冲区再次为空,当前进程被唤醒,将此组用户数据的未发送部分复制到缓冲区,继续发送。 (2)copy_to_Tx_buf函数。此函数主要用于缓冲区正在发送且未发送完毕的情况,将新一组用户数据copy至缓冲区。首先计算缓冲区剩余空间,若剩余空间大于本组用户数据大小,则直接将用户数据全部copy至缓冲区;若剩余空间小于本组数据大小,则copy与剩余空间大小相同的用户数据至缓冲区。 写操作的具体流程如图1所示,首先用户数据从空间态转换到内核态,并设置相应的接收标志位。此后判断数据大小。若数据大于缓冲区空间,数据发生溢出,写操作结束;若没有溢出,为了保证进程间的数据,使得该进程获得自旋锁,此时判断缓冲区是否为空。根据上面两个函数的介绍,在不同情况下分别调用不同的函数,在数据写入环形缓冲区后,将数据发送到SPI的发送寄存器。当SPI发送寄存器发送数据时,环形缓冲区依旧接收数据,如果此时缓冲区为满,则释放自旋锁,并设置进程等待标志位(wait_Tx_done),将此进程休眠,直到发送寄存器中的数据发送完毕,再唤醒进程,判断数据是否全部发送完毕。若仍有数据等待发送,则调用copy_to_Tx_buf_int;若数据已全部发送完毕,则写操作结束。若缓冲区不为满,则判断数据是否发送完毕。数据全部发送完毕,发送操作结束。 2.3SPI读操作 读操作是连续读取主SPI发送到从SPI的接收缓冲区中的数据,并将其传送给用户空间。具体流程如图2所示。首先判断操作标志位spi_Rec_en,若此位为0,说明此时驱动正处于发送状态,则将发送进程等待标志位(wait_Tx_done)置1,读进程进入休眠状态即放入等待队列中,等待中断处理函数中相关发送程序唤醒。若操作标志位不为1,读进程首先获得自旋锁,判断数据大小。若数据大小不为0且不超过缓冲区大小,则按照S3C2440接收数据的要求,向SPI发送寄存器写入第一个dummy数据(0xff)。此后,将接收进程等待标志位(wait_Rec_done)置1,释放自旋锁,并将此进程加入等待队列进行休眠,直到用户要求的所有数据已发送至接收缓冲区后,由中断处理函数唤醒该进程,最后将接收区中的数据放到临时接收缓存中,以便于其他操作读取。 3SPI驱动程序测试 SPI驱动程序主要通过调用写操作,使SPI连续发送数据0x55,此后再调用SPI读操作,将MISO上的串行数据读入用户缓冲区,并与实际数据进行比较。图3为示波器测试MOSI引脚波形。图中波形1为SCK信号,ARM系统时钟为40MHz,SPI的SCK信号为系统时钟的256分频,约为156kHz;波形2为MOSI信号,SPI从低位向高位串行移位。通过波形可以看出,SPI驱动能够准确地完成读写操作,验证了其正确性。

    时间:2021-03-23 关键词: ARM S3C2440 Linux

  • 6个“吓人”的Linux命令

    crypt 好吧,我们一直都有crypt。顾名思义,crypt不是存放垃圾文件的地宫或墓坑,而是加密文件内容的命令。 如今,“crypt”通常作为一个脚本而实现:通过调用一个名为mcrypt的二进制程序,模拟较旧的crypt命令,从而发挥其功用。直接使用mycrypt命令是一种更好的选择。 $ shred dupes.txt $ more dupes.txt ▒oΛ▒▒9▒lm▒▒▒▒▒o▒1־▒▒f▒f▒▒▒i▒▒h^}&▒▒▒{▒▒ zombies 虽然zombies(僵尸进程)不是一个命令,但它在Linux系统上却根深蒂固。zombies基本上是没有被完全清除的死亡进程的残骸。 进程不应该以这种方式运行——任由死亡进程逗留,而不是仅仅让它们死亡、进入数字天堂,所以zombies的存在表明了留下它们的进程存在某种缺陷。 检查你的系统是否有僵尸进程残留下来,一个简单的方法就是查看top命令的标题行。 好吓人!上面显示有三个僵尸进程。 $ ps -ef | grep sshd root 1142 1 0 Oct19 ? 00:00:00 /usr/sbin/sshd -D root 25342 1142 0 18:34 ? 00:00:00 sshd: shs [priv] $ ps -ef | grep daemon | grep -v grep message+ 790 1 0 Oct19 ? 00:00:01 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation root 836 1 0 Oct19 ? 00:00:02 /usr/lib/accountsservice/accounts-daemon

    时间:2021-03-23 关键词: crypt Linux

  • Linux设置动态库路径和环境变量

    pi@NanoPi-NEO-Plus2:~$ ldd untitled         linux-vdso.so.1 =>  (0x0000ffffba839000)         libQt5Widgets.so.5 => not found         libQt5Gui.so.5 => not found         libQt5Core.so.5 => not found         libpthread.so.0 => /lib/aarch64-linux-gnu/libpthread.so.0 (0x0000ffffba7e2000)         libstdc++.so.6 => /usr/lib/aarch64-linux-gnu/libstdc++.so.6 (0x0000ffffba653000)         libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x0000ffffba5a6000)         libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000ffffba585000)         libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffffba43e000)         /lib/ld-linux-aarch64.so.1 (0x0000ffffba80e000) 最笨的方法就是将编译出来对应的so 拷贝到/usr/lib或者/lib下,如果对应的so很多,那么就凉凉了。 设置方法: 1)在/etc/ld.so.conf.d路径下,创建动态库配置文件*.conf,例如: sudo vim /etc/ld.so.conf.d/Qt5.conf 在文件中添加: /usr/local/aarch64_qt5.12.0/lib 2)加载动态库配置 执行命令:sudo ldconfig

    时间:2021-03-18 关键词: 环境变量 动态库路径 Linux

  • Linux杀死了商业版Unix?

    商用 Unix 的销售量已经断崖式下跌。这种急剧下降的背后一定有什么原因。Linux 是否已经杀死了它的祖先,成为了一个完全可行的替代品,就像操作系统版的《天外魔花》(Invasion of the Body Snatchers)?Unix 起源Unix 首次发布是在 52 年前的 1969 年,诞生于 AT&T 旗下的研发公司贝尔实验室。其实,当时它还叫 Unics,代表 UNIplexed Information and Computing Service。显然,没有人记得「cs」是什么时候变成「x」的。它是在 DEC PDP/7 计算机上用 DEC 汇编语言编写的。后来,由于贝尔公司内部需要制作排版的专利申请,Unix 开发团队发现这种需求是一个契机,利用这个契机他们可以使用到更新、更强大的 DEC PDP/11/20 计算机,所以他们很快就用 Unix 制作了一个排版程序来生成专利申请书。 此后,Unix 的使用在贝尔公司稳步增长。1973年,Unix 的第 4 版发布了,用 C 语言重新编写而成。附带手册的介绍中有这样一段话。“The number of UNIX installations is now above 20, and many more are expected.” (K. Thompson and D. M. Richie, The UNIX Programmer’s Manual, 4th ed. November 1973.)"UNIX 的安装数量现在已经超过了 20 个,而且预计还会有更多的安装" (K. Thompson 和 D. M. Richie,UNIX 开发者指南,第4版,1973年11月)。 1973年,Ken Thompson 和 Dennis Ritchie 这两位 Unix 的核心架构师在一次关于 Unix 的会议上发表了一篇论文。他们立即收到了索取操作系统副本的请求。 早在 1956 年 AT&T 就与美国政府签订的同意令,AT&T 不得不退出“除提供普通运营商通信服务以外的任何业务"。但是他们可以授权贝尔实验室的产品,不过他们不能全心全意地将它们产品化。所以 Unix 操作系统是以源代码的形式发行的,有许可证,成本包括运输和包装以及“合理的版税“。 因为 AT&T 不能把 Unix 当做一个产品来对待,因此没有给它加上通常的包装,而且 Unix 也没有得到任何营销。它没有任何支持,也没有错误修复。尽管如此,Unix 还是传播到了大学、军事应用,并最终进入了商业世界。 由于 Unix 是用 C 编程语言重写的,所以将它移植到新的计算机架构上相对容易,很快 Unix 就在各种硬件上运行。它已经突破了 DEC 产品范围的限制,现在几乎可以在任何地方运行。商业 Unix 的崛起1982年,在签署另一项同意令之后,AT&T 被迫放弃对贝尔公司的控制权,贝尔公司被拆成了较小的区域性公司。这次动荡也使 AT&T 摆脱了以前的一些束缚。他们现在可以正式将 Unix 产品化。1983 年,AT&T 将授权许可证费用提高了,后续的支持和维护也终于跟上了。 正是这种商业化的趋势促使 Richard Stallman 创建了 GNU 项目,旨在编写一个完全摆脱 AT&T 源代码的 Unix 版本。而如今距离 GNU 项目的诞生,也已经过去了 38 年了。 当然,那些在之前的软件许可证下已经拥有 Unix 源代码的人,能够坚持使用那个版本。因此在没有 AT&T 支持的情况下,这些用户只能自行或者是在 Unix 用户社区下以技术自助小组的形式对 Unix 进行了修改、扩展和修补。 IBM、HP、Sun、Silicon Graphics 以及更多的硬件供应商都有自己的 Unix 专有商业版本或类 Unix 的操作系统。 Unix 逐渐成为医疗保健和银行等市场中关键任务工作负载的首选操作系统。航空航天、汽车和造船业制造商,以及世界各地的大学也广泛采用了 Unix。 当 Unix 被移植到个人电脑上时,特别是当更强大的英特尔 80386 处理器在 1985 年发布时,Unix的安装量急剧上升。Unix现在可以在大型机、微型计算机和个人计算机上使用。Unix 战争80 年代末和 90 年代初,各种 Unix 版本之间为争夺主导地位和标准化进行了长期而混乱的斗争。很明显,所有的利益相关者都想成为被公认为是黄金标准的那一个。最终,标准本身被引入,以尝试解决兼容性问题。 这导致了单一 UNIX 规范(也包括 POSIX 标准)的产生。大写字母"UNIX"现在是 Open Group 的商标,它被保留给符合 Single UNIX 规范的操作系统,"Unix"指的是一个操作系统家族,其中一些可以自称 UNIX。 这是对这一时期的一个非常精炼的总结,对于当时可能会购买 Unix 的人来说,这个时期的困惑可能比我们回过头来看更多。不用说,如果客户不知道该买什么,他们就会暂缓购买,观察事态的发展,Unix 销售量也大大放缓。 这对商业 Unix 来说是一个创伤,但还不致命。Linux1991年,芬兰计算机科学学生 Linus Torvalds 发表了他著名的声明,他正在开发一个操作系统内核,作为一种爱好。他的动机是学习 386 CPU 的架构。2021 年,Linux 已诞生 30 周年。 Richard Stallman 的 GNU 项目已经编写了许多类 Unix 操作系统的元素,但他们的内核 GNU Hurd 还没有。Linus Torvald 的 Linux 内核填补了这个空白。 有了 Linux 内核和 GNU 操作系统的工具和实用程序,一个完全可以运行的类 Unix 的操作系统诞生了。纯粹主义者会将其称为 GNU/Linux,我们其他人则使用 "Linux"这个简写版本。只要对两个阵营的贡献表示赞赏、尊重和认可,无论哪种方式我们都很高兴。 自 1991 年以来,Linux 的功能、完整性和稳定性都在稳步提升。现在,它在不同的用例和产品中被发现,数量惊人。 最古老的发行版是 Slackware,它发布于 1993 年。它是基于前一年发布的名为 Softlanding Linux 系统的早期发行版。Slackware 试图成为众多 Linux 发行版中最像 Unix 的一个。 Linux 的崛起无成本的类 Unix 的操作系统的吸引力,再加上对源代码的访问,是一个令人信服的信息。而如今,Linux 已无处不在。它驱动着网页。W3Techs 报告称,在 Alexa 排名前 1000 万的域名中,有 70% 使用了 Linux。它驱动着公有云。在 Amazon EC2 上,Linux 占服务器的 92%,拥有超过 35 万个独立实例。它驱动着世界上最快的计算机。世界上最快的 500 台超级计算机都在运行 Linux。它迈入了太空。猎鹰9号火箭的飞行计算机运行的是 Linux。它在你的口袋里。Google 的 Android 系统的核心是 Linux 内核。目前有超过 25 亿台活跃的 Android 设备。这包括 Chromebook和其他设备。(苹果 iOS 的核心是由加州大学伯克利分校开发的Unix变种 "伯克利软件发行版"(BSD)直接衍生出来的代码)。因此,无论你对智能手机的偏好如何,它们都依赖于类 Unix 操作系统的元素。它驱动着智能家居。你家里有智能小工具吗?几乎可以肯定它就是运行的嵌入式 Linux。它驱动着你的网络。大多数管理型交换机、无线接入点和路由器都运行在嵌入式 Linux 上。它为电信通信提供动力。你的办公桌上有一部 VOIP 电话,或者通讯室里有一台电话交换机?它们可能运行的是嵌入式 Linux。它就在你的电脑里。即使你没有运行 Linux桌面,微软也会在 Windows 10 的 Windows Subsystem for Linux 中加入 Linux 内核。它就在汽车里面。特斯拉(以及其他汽车制造商)在他们的汽车中使用 Linux。除了在个人电脑上,Linux 在任何地方都占主导地位。甚至微软也在通过 Windows Subsystem for Linux 从它的桌面端向 Linux 世界示好。 但这次讨论的重点是 Unix 和 Linux,而不是Linux 和 Windows。而如今,Unix 曾经占据的领域,Linux 同样现在也在,而且 Linux 还占据了一些 Unix 从未去过的地方。Linux 以无处不在。 IBM 是商业 Unix 最后的坚持者之一,它的 AIX 产品。即便如此,IBM 也在拥抱 Linux,花费了340 亿美元收购红帽,并且与其内部产品形成正面竞争。有趣的是,IBM 速度最快的超级计算机运行的是红帽企业 Linux,而不是AIX。Linux 比 Unix 好吗?不,它们或多或少是同样优秀的,各有各的特点。只不过 Linux 在泛用性方面更加优秀,比如可以运行在从超级计算机到Raspberry Pi 的任何设备上。你可以得到源代码,有一个充满热情的用户和维护者社区,而且它是免费提供的。 如果你想要商业支持,也可以从 Red Hat、Canonical 和 Oracle 获得。而这也是 Linux 能够从一些企业中取代 Unix 的关键之处,因为很多公司不相信 "免费",他们更乐意为支持付费。Linux 的崛起并不都是以 Linux 免费为前提的。商业 Linux 帮助击败了商业 Unix。 Linux 比 Unix 更成功吗?好吧,这也取决于对给成功的定义。如果拥有比其他操作系统更多样化和更广泛的使用是一个衡量标准,那么是的。如果是运行该操作系统的设备数量最多,那么是的。 红帽公司以 340 亿美元的价格出售,可能也是Linux 在商业成功方面上的一次成功。Linux 杀死了 Unix 吗?更准确地说,是 Linux 让 Unix 停住了脚步,然后迈入了 Unix 的赛道。 Unix 仍在那里,运行着关键任务系统,这些系统功能正常,运行稳定。这种情况会一直持续下去,直到对应用程序、操作系统或硬件平台的支持停止。 但是对于新的安装来说呢?有足够多的 Linux 变体,使得选择商用 Unix 的理由非常非常困难。END来源:开源中国作者:Dave Mckay;编译:Alias_Travis免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-03-18 关键词: Unix Linux

  • 基于Linux/QT与GPRS的远程集群式心脏病人实时诊断系统

    基于Linux/QT与GPRS的远程集群式心脏病人实时诊断系统

    0 引言 在当今社会,人们的生活水平普遍提高,工作强度越来越大,营养的过剩和运动量的减少,导致心脑血管疾病的发病率是越来越高。随着社会老龄化趋势的加剧,解决长期慢性病的监护特别是心脑血管疾病的监护已经是重要的社会问题。随着GPRS远程通信技术和短距离无线网络通信技术的不断发展和成熟,实时远程监控技术也逐步成熟,GPRS网络通信业务是通信公司推出的一项数据传输通信业务,在GPRS网络覆盖区域内,传输距离不受限制,通信费用相对低廉,传输速率较快。ZigBee短距离无线通信技术是一种近距离、低复杂度、低功耗、低速率、低成本的双向无线通信技术,主要用于距离短、功耗低且传输速率不高的各种电子设备之间进行数据传输以及典型的有周期性数据、间歇性数据和低反应时间数据传输的应用。但现有的远程心电监护系统和远程移动心电监护系统在实际临床推广中,尤其是对院外高危心脏病人的监护,仍然存在诸如病人活动范围受限、不具备同时多人监护功能、不具备病人地理定位功能等不足,并未开发出成熟、实用的系统。本文解决了嵌入式Linux/QT人机界面、GPRS远程通信、ZigBee无线通信同步实时监护心电、血压、血氧、体温等多生理参数并传送等相关技术难点,分析了其各自基本特点和所要实现的基本功能,并在此基础上提出了基于Linux/QT嵌入式系统和ZigBee网络及GPRS无线通信的心脏病人实时诊断系统的总体解决方案。 1 系统远程移动终端总体设计方案 本文是把先进的无线通信技术和计算机技术应用于远程监护系统,针对心脑血管疾病患者在医疗监护方面的特殊背景及临床救助要求,研制基于无线通信网络技术及GPS全球卫星定位系统的远程集群诊断急救系统,用户通过各种便携或手持无线通信设备将病人重要的生理信息通过无线通信方式实时、准确、快速地传送到远程医疗中心,使病人在家庭、社区随时可以享受医疗服务并得到医生的专业指导,从而实现远程急救、远程监护、远程会诊,最大限度防止患者发生猝死。这样不仅可以加强对危重病人和心血管等突发性疾病的预防监护和实施急救,还可以实现医院资源共享,提高医疗服务水平,减小病人的负担,提高人民的生活质量和健康水平。同时,针对偏远地区或者农村的病人,交通不便,医疗资源有限,看病难、看病贵的问题。 远程移动终端硬件系统组成框图如图1所示。 远程移动终端的硬件采用模块化设计,以ARM11S3C6410控制芯片为核心控制器,完成所有心电数据的处理,包括数据的采集与控制命令的发出,是整个系统的控制核心,采用Linux嵌入式系统为监控系统,能够自动运行,处理数据,同时,控制器还采用Linux/QT完成人机界面的编写,通过ZigBee无线通信协议完成患者体征数据采集,通过GPS信息采集实现人机接口与信息分析诊断中心的GSM/GPRS/3G通信、电源管理等功能。 2 数据的采集、处理与传输 2.1 数据采集模块 完成患者生理信号的采集、放大和滤波过程;为ARM11S3C6410系统提供能直接读取的信号,采集终端生理信息存储时间为24 h以上;在远程移动终端中集成GPS卫星定位系统,能够实时采集GPS芯片输出的地理位置信息。将已压缩的患者心电等信息和GPS经纬度及高度等信息通过GPRS/3G通信网络上传给信息分析诊断中心的数据库中。当患者心电等出现异常时,信息分析诊断中心的GIS系统根据移动终端上传的GPS信息自动指示病人目前所处的地理位置。为信息分析诊断中心实时提供患者的地理信息,使患者能够得到快捷、准确的救助。 需要采集患者的体征信息如下: (1)心电:包括心电波形、心率。心电波形采样率为300 Hz。 (2)血氧:包括血氧波形、脉率。血氧波形采样率为50 Hz。 (3)血压:包括收缩压、舒张压和平均压。 (4)体温、呼吸。 2.2 数据处理模块 数据处理模块的硬件设计是以ARM/SoPC芯片为核心;在ARM/SoPC中集成了相应的处理器;在处理器上移植了嵌入式操作系统。后台专家分析诊断急救系统则是运行在操作系统上的应用软件;软件中的专家系统根据采集患者生理信息,对患者的实时状态做出判断,给出相应级别的救治建议。主要功能如下: (1)心律失常分析,对大量心率数据进行统计分析; (2)血压状态监护的模糊判断; (3)体温、血氧生理指标的模糊判断。 结合以上体征指标的统计分析和模糊判断,智能专家系统推理判断患者的实时状态,提供相应的救治意见。 2.3 数据传输模块 远程集群实时诊断急救系统由移动终端和信息分析诊断中心两部分组成,一个信息分析诊断中心可以同时监护多个病人,实时的接收、存储、处理远程用户终端通过GSM/GPRs/3G无线移动网络传送的数据,远程移动终端数据传输系统的整体结构如图2所示。 BSSG基站系统用以实现BSS和SGSN之间路由和其他信息的传送。SGSN的主要作用是记录移动台的当前位置信息,并且在移动台和GGSN之间完成移动分组数据的发送和接收。GGSN主要是起网关作用,它可以和多种不同的数据网络连接,如ISDN,PSPDN和LAN等。GGSN可以把GSM网中的GPRS分组数据包进行协议转换,从而可以把这些分组数据包传送到远端的TCP/IP或X.25网络。 3 终端数据采集与分析 整个系统在实际工作中传输的数据量非常大,可能会出现数据堵塞的问题,在终端系统的设计中首先进行前期的数据分析与处理,如图3所示,采用每1 min进行一次基于多权值算法求平均值,然后只需对所求值进行传输就可以,减少了传输数据,增强了数据传送的稳定性。 4 系统软件 系统采用Linux操作系统,Linux内核是一种源码开发的操作系统,采用模块化设计。在此只保留了必须的功能模块,删除了冗余的功能模块,并对内核重新编译,从而使系统运行所需的硬件资源显著减少。Linux系统内核集成了大量的网络应用程序,支持全部的标准因特网协议和技术所有的互联网技术,因此将其应用于远程集群式心脏病人实时诊断系统的设计,具有代码量小、运行消耗系统资源少、可靠性高,开发周期短等优点,适应实时诊断系统采集控制及传输要求。QT作为一种跨平台的基于C++的GUI系统,能够提供给用户构造图形用户界面的强大功能。本文选用移植性强的QT软件设计图形用户界面,所设计的GUI实用、简洁,实现了人机交互,可通过对程序进行输入、保存、修改和编译,信息和临时信息及时输出显示达到整合系统的目的。本文采用QT应用进程之间通信机制SignalSlot和FIFO机制。Linux系统不断侦查本地GUI信息,任何一个QT消息被触发,系统都会立即执行相应程序,提高整个系统的反应速度和稳定性。系统人机界面Linux/QT执行程序及相关硬件挂载如下: 5 结语 系统的设计利用ARM11S3C6410的硬件功能及处理速度,移植了以S3C6410为硬件核心的Linux嵌入式系统,完成了基于Linux/QT的人机界面的程序开发与编写,解决了包括基于S3C6410的GPRS远程通信,数据传送等多项技术难点。试验产品控制效果良好,验证了本系统的先进性、稳定性与实用性,具有推广与应用的价值。

    时间:2021-03-18 关键词: GPRS QT 远程集群式 心脏病人实时诊断系 Linux

  • What,航天器、导弹喜欢用单片机?为什么不是嵌入式系统?

    一、前言 二、关于单片机与嵌入式系统之间界定 1. 单片机 2. 嵌入式系统 3. 嵌入式 Linux 三、非实时、软实时、硬实时 四、x86 Linux 系统的调度策略 1. 为什么 Linux 系统是软实时? 2. Linux 系统如何改造成硬实时? (1) RT-Preempt (2) Xenomai 五、RTOS 的优势 六、总结 一、前言 前几天和一个在某研究所的发小聊天,他说:现在的航空、航天和导弹等武器装备中,控制系统几乎都是用单片机,而不是嵌入式系统。 乍一听,和我们的直觉有矛盾啊:那么高大上的设备,其中的控制逻辑一定很复杂,不用嵌入式系统怎么来完成那么复杂的功能控制啊?然后仔细了解了一下,才明白答案是:安全+可控。 这篇文章我们就来聊一下关于单片机与嵌入式、操作系统与 RTOS 之间的那些事!通过这篇文章,让你操作系统的实时性有一个系统、全面的理解! 二、关于单片机与嵌入式系统之间界定 说实话,关于它俩的区分,没有人可以给出一个标准的、正确的答案。每个人理解的单片机与嵌入式系统,都是略有差别的。 抛开硬件,从应用程序开发的角度来看,我是这样来理解的: 单片机:可以直接使用状态机来实现程序框架,也可以利用一些 RTOS(ucOS、FreeRTOS、vxWorks、RT-Thread)等来完成一些调度功能。 嵌入式系统:利用嵌入式 Linux 操作系统以及一些变种来编写应用程序。 我知道自己的理解可能是不对的,至少不严谨、范围狭隘,既然没有标准答案,那姑且引用维基百科中的定义吧,毕竟概念是死的,更重要的是我们如何根据实际的需要来进行选择。 1. 单片机 单片机,全称单片微型计算机(single-chip microcomputer),又称微控制器单元 MCU(microcontroller unit)。 把中央处理器、存储器、定时/计数器、各种输入输出接口等都集成在一块集成电路芯片上的微型计算机。 由于其发展非常迅速,旧的单片机的定义已不能满足,所以在很多应用场合被称为范围更广的微控制器; 2. 嵌入式系统 嵌入式系统(Embedded System),是一种嵌入机械或电气系统内部、具有专一功能和实时计算性能的计算机系统。 嵌入式系统常被用于高效控制许多常见设备,被嵌入的系统通常是包含数字硬件和机械部件的完整设备,例如汽车的防锁死刹车系统。 现代嵌入式系统通常是基于微控制器(如含集成内存和/或外设接口的中央处理单元)的,但在较复杂的系统中普通微处理器(使用外部存储芯片和外设接口电路)也很常见。 3. 嵌入式Linux 嵌入式Linux(英语:Embedded Linux)是一类嵌入式操作系统的概称,这类型的操作系统皆以Linux内核为基础,被设计来使用于嵌入式设备。 与电脑端运行的linux系统本质上是一样的,虽然经过了一些功能上的裁剪,但是本质上是一样的,主要利用 Linux 内核中的的任务调度、内存管理、硬件抽象等功能。 4. RTOS 实时操作系统(RTOS),又称即时操作系统,它会按照排序运行、管理系统资源,并为开发应用程序提供一致的基础。 实时操作系统与一般的操作系统相比,最大的特色就是“实时性”,如果有一个任务需要执行,实时操作系统会马上(在较短时间内)执行该任务,不会有较长的延时。这种特性保证了各个任务的及时执行。 三、非实时、软实时、硬实时 首先要明白什么叫实时性?实时性考虑的不是速度、性能、吞吐量,而是确定性,也就是说:当一个事件发生的时候,可以确定性的保证在多长时间内得到处理,只要能满足这个要求,就可以成为硬实时。比如: 操作系统1:当中断发生时,可以保证在 1 秒内得到这里,那么它就是硬实时系统,虽然响应时间长,但它是确定的;操作系统2:当中断发生时,几乎都可以在 1 毫秒内完成,那么那就不能成为硬实系统,虽然响应时间短,但是它不确定。 也看到有文章说:应该取消软实时这个模棱两可的说法,要么是实时,要么是非实时! 操作系统包含的功能很多:任务调度、内存管理、文件管理等等,其中最核心的就是任务调度,这也是非实时、软实时、硬实时的最大区别。 也就是说,衡量实时性的指标就是: 1. 中断延时:一个外部事件引发的中断发生时,到相应的中断处理程序第一条指令被执行时,所经过的时间;2. 任务抢占延时:当一个高优先级的任务准备就绪时,从正在执行的低优先级任务中抢夺 CPU 资源所经过的时间; 不同的操作系统,其任务调度机制也是不一样的,而这个调度机制的策略,又是与实际的使用场景相关的。因此,并不存在哪个好、哪个不好这样的说法,合适的就是最好的! 比如:我们的桌面系统,需要考虑的是多任务、并发,需要同时执行多个程序,哪个程序慢一点,用户无所谓,甚至觉察不到;但是对于一个导弹控制系统,当一个外部传感器输入信号,触发一个事件时,对应的处理必须立刻执行,否则耽搁 1 毫秒,结果可能就是差之千里! 四、x86 Linux 系统的调度策略 我们日常使用的 PC 机,它的主要目标是并行执行多任务,强调的是吞吐率(尽可能多的执行很多应用程序的代码),因此,采用的是分时操作系统,也就是每个任务都有一个时间片,当一个任务分配的时间片用完了,就自动换出(调度),然后执行下一个任务。 我们平常在写 x86 平台上写普通的客户端程序时,很少需要指定应用程序的调度策略和优先级,使用的是系统默认的调度机制。反过来说,也就是在某些需要的场合下,是可以设置进程的调度策略和优先级的。 例如在 Linux 系统中,可以通过 sched_setscheduler() 系统函数 设置 3 种调度策略: 1. SCHED_OTHER: 系统默认的调度策略,计算动态优先级(counter+20-nice),当时间片用完之后放在就绪队列尾;2. SCHED_FIFO: 实时调度策略,根据优先级进行调度,一旦占用CPU就一直执行,直到自己放弃执行或者有更高优先级的任务需要执行;3. SCHED_RR: 也是实时调度策略,在 SCHED_FIFO 的基础上添加了时间片。在执行时,可以被更高优先级的任务打断,如果没有更高优先级的任务,那么当任务的执行时间片用完之后,就会查找相同优先级的任务来执行。 1. 为什么 Linux 系统是软实时的? 可能有小伙伴会有疑问:既然 Linux 系统中提供了 SCHED_FIFO 基于优先级的调度策略,为什么仍然不能称之为真正的硬实时操作系统?这就要从 Linux 的发展历史说起了。 Linux 操作系统在设计之初,就是为了桌面应用而开发的,在那个时代,多个终端(电传打字机和屏幕)连接到同一个电脑主机,需要处理的是多任务、并行操作,并不需要考虑实时性,因此,在 Linux 内核中的一些基因,严重影响了它的实时性,例如有如下几个因素: (1) 内核不可抢占 我们知道,一个应用程序在执行时,可以在用户态和内核态执行(当调用一个系统函数,例如:write 时,就会进入内核态执行),此时任务是不可抢占的。 即使有优先级更高的任务准备就绪,当前的任务也不能立刻停止执行。而是必须等到当前这个任务返回到用户态,或者在内核态中需要等待某个资源而睡眠时,高优先级任务才可以执行。 因此,这就很显然无法保证高优先级任务的实时性了。 (2) 自旋锁 自旋锁是用于多线程同步的一种锁,用来对共享资源的一种同步机制,线程反复检查锁变量是否可用。由于线程在这一过程中保持执行,因此是一种忙等待。一旦获取了自旋锁,线程会一直保持该锁,直至显式释放自旋锁。 自旋锁避免了进程上下文的调度开销,因此对于线程只会阻塞很短时间的场合是有效的,也就是说,只能在阻塞很短的时间才适合使用自旋锁。 但是,在自旋锁期间,任务抢占将会失效,这就是说,即使自旋锁的阻塞时间很短,但是这仍然会增加任务抢占延时,让调度变得不确定。 (3) 中断的优先级是最高的 任何时刻,只要中断发生,就会立刻执行中断服务程序,也就是中断的优先级是最高的。只有当所有的外部中断和软终端都处理结束了,正常的任务才能得到执行。 这看起来是好事情,但是想一想,如果有比中断优先级更高的任务呢?假如系统在运行中,网口持续接收到数据,那么中断就一直被执行,那么其他任务就可能一直得不到执行的机会,这是影响 Linux 系统实时性的巨大挑战。 (4) 同步操作时关闭中断 如果去看 Linux 内核的代码,可以看到在很多地方都执行了关中断指令,如果在这期间发生了中断,那么中断响应时间就没法保证了。 2. Linux 系统如何改成硬实时? 以上描述的几个因素,对 Linux 实现真正的实时性构成了很大的障碍,但是现实世界又的确有很多场合需要 Linux 具有硬实时,那么就要针对上面的每一个因素提出解决方案。 目前主流的解决方案有 2 个: 单内核解决方案:给 Linux 内核打补丁,解决上面提到的几个问题,例如:RT-Preempt; 双内核解决方案:在硬件抽象层之上,运行 2 个内核:实时内核 + Linux 内核,它们分别向上层提供 API 函数,例如:Xenomai; 这 2 种解决方案分别有不同的实现,从调研情况来看,RT-Preempt 和 Xenomai 是使用比较多的,下面分别来看一下他们的优缺点。 (1)RT-Preempt 这种方式主要是对 Linux 内核进行打补丁,解决了上面所说的几个问题:内核不可抢占、自旋锁、关中断以及终端优先级的问题。 至于每一个问题是如何解决的,由于篇幅关系,这里就不介绍了,感兴趣的小伙伴如果需要的话,可以深入了解一下。 由于是直接在 Linux 内核上打补丁(以后肯定会合并到主分支中的),因此对于应用程序开发来说,操作系统向上层提供的 API 接口函数可以保持不变,这对应用程序开发来说是一件好事情。 (2)Xenomai Xenomai是一个 Linux 内核的实时开发框架,它希望通过无缝地集成到 Linux 环境中来给用户空间应用程序提供全面的,与接口无关的硬实时性能。下面是 Xenomai 的架构图: 在硬件抽象层之上,是 2 个并列的域(内核),这 2 个内核分别向上层提供自己的 API 接口函数。 图中 glibc 是 Linux 系统提供的库函数,应用程序通过调用库函数和系统调用来编写程序。 Xenomai 也提供了相应的库函数 libcobalt ,这个库函数是需要我们在用户层编译、安装的,就像安装第三方库一样。 此外,Xenomai 还参考不同的操作系统风格,提供了好几套 API 函数(之前的说法是:皮肤),API 接口函数在这里: 从图中可以看到,Alchemy API 这套接口提供的功能更完善,提供了:定时器、内存管理、条件变量、事件、互斥锁、消息队列、任务(可以理解为线程)等 API 函数。这一套 API 函数中具体的功能与 POSIX 标准大体相同,在一些细节上存在一些差异。 由于 Xenomai 向应用层提供的 API 函数是独立的一套,因此,如果我们需要创建实时任务,那么就要调用这一套接口函数来创建任务,包括使用其中的一些资源(例如:内存分配)。而且文档中也提出了一些注意点,例如:某些资源不能在 Xenomai 与 Linux 系统之间混用。 五、RTOS 的优势 上面已经说到,Linux 桌面系统的主要目标是吞吐量,在单位时间内执行更多的代码。 但是对于单片机来说,首要目标不是吞吐量,而是确定性,因此衡量一个实时操作系统坚固性的重要指标,是系统从接收一个任务,到完成该任务所需的时间。也就是说,任务调度才是第一考量要素。 在单片机开发中,一般有 2 种编程模型:基于状态机(裸跑),基于 RTOS。 如果基于状态机,就不存在任务调度问题了,因为只有一个执行序列,所有的操作都是串行执行的,唯一需要注意的控制流程就是中断处理。 如果基于 RTOS,主要利用的就是任务调度,实现真正的硬实时。这方面最牛逼的就是VxWorks了,当然价格也是非常可观的,有些公司购买之后,甚至会把除了任务调度模块之外的其他模块全部重写一遍,这也足以证明了 VxWorks 在任务调度处理上的确很厉害,这也是它的看家本领! 当然,对于简单、需要严格控制执行序列的关键程序来说,使用有限状态机的编程框架,一切都在自己的掌握中。只要代码中没有 bug,那么理论上,一切行为都是在控制之中的,这也是为什么很多军事设备上使用单片机的原因! 六、总结 关于任务调度的问题,是一个操作系统的重中之重,其中需要学习的内容还有很多,最近刚买了一本陈海波老师的新书,也就是华为的鸿蒙系统背后的灵魂人物。 如果有新的学习心得,再跟大家分享。 参考文献: https://linuxfoundation.org/blog/intro-to-real-time-linux-for-embedded-developers/https://wiki.archlinux.org/index.php/Realtime_kernel_patchsethttp://www.faqs.org/faqs/realtime-computing/faq/https://xenomai.org/documentation/xenomai-3/html/README.INSTALL/ 好文章,要转发;越分享,越幸运!    END 来源:IoT物联网小镇,作者:道哥 版权归原作者所有,如有侵权,请联系删除。 ▍ 推荐阅读 你怎样选择开源免费RTOS? GD32也开始假货翻新泛滥了 工程师姓什么很重要!别再叫我“X工”!!! →点关注,不迷路← 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-03-17 关键词: 嵌入式 单片机 RTOS Linux

  • 揪出元凶:linux定时任务crontab居然没执行

    本文能学到 •busybox为例粗略跟踪软件执行过程方法 •如何判断文件差异 •cron 对任务计划文件要求 1. 背景 无意中瞟一眼出厂产品的日志文件 /app/recode 大小居然有9MB,按照设计每10min执行任务检查/app/recode文件大小,该文件不会超过4MB,超过此大小则压缩处理,仅保留最近的日志内容。立马着手检查linux定时任务cron运行情况。 2. 初步排查 执 crontab -e 查看定时任务配置情况,其实是以root权限打开 var/spool/cron/crontabs/root 文件,第二行是本背景该执行的脚本,乍看一下没有任何问题。检查 /var/log/message 看是否有被执行的记录,“cat /var/log/message | grep cron”,干干净净!!!的确没被执行。 本来事情到此为止只算工程师一个平常无奇的日常,不过10min后再查看 /app/recode 居然从9MB变成4KB,/var/log/message也有执行记录,发生了什么? 3. 分析 为了分析具体原因,准备一新烧录的板卡作为排查对象。怀疑方向有三个,这三方面都是引起任务计划不被执行的诱因: crontab file格式不正确 文件系统被改写 crontab file所属用户不合法 3.1. x11 crontab file 格式不正确 crontab file文件位于 var/spool/cron/crontabs/root,当使用crontab -e命令打开该文件,不做任何修改并退出,cron任务计划能被运行。 怀疑var/spool/cron/crontabs/root文件里可能包含不合法字符或语法不正确,如:文件末尾有\r、\n、一行里有多个空格会影响cron解析该文件。 于是执行如下步骤排查: 1.备份配置文件 cp var/spool/cron/crontabs/root var/spool/cron/crontabs/root.bak; 2.执行crontab -e; 3.cron任务计划是否被执行,需查看记录 watch -n 1 cat /var/log/message。 4.计算两文件md5是否一致 md5sum var/spool/cron/crontabs/root var/spool/cron/crontabs/root.bak; 结果:文件一致。 证明:“crontab file 格式不正确”不是诱因。 3.2. x12 文件系统被改写 crontab -e虽然没有修改var/spool/cron/crontabs/root,但无法证明它有没有改写文件系统其他文件。于是在一块重新烧录镜像的板卡执行如下步骤排查: 获取文件系统所有文件的MD5保存为/tmp/a.txt; find arch bin etc home lib media opt \root sbin tmp usr var -name "*" | \xargs md5sum > /unuse/a.txt 执行crontab -e; 获取文件系统所有文件的MD5保存为/tmp/b.txt; find arch bin etc home lib media opt \root sbin tmp usr var -name "*" | \xargs md5sum > /unuse/b.txt 比较a.txt和b.txt是否一致,从而证明crontab -e是否修改文件系统内容 结果:a.txt,b.txt文件一致。 证明:“x12 文件系统被改写”不是诱因。 3.3. x13 crontab file所属用户不合法 产品的cron是busybox的组件,源码面前无秘密。开始跟踪crond执行过程。 在busybox源码的miscutils/crond.c添加若干 “printf(”LINE %d", __ LINE __);"跟踪程序运行。 cron在前台运行,执行crond -f var/spool/cron/crontabs/root; 发现947行没有被执行,且文件指针是0; 推断:var/spool/cron/crontabs/root没有被读取。 跟踪文件读取函数load_crontab发现438行的if第二个条件不满足,DEAMON_UID是0,只有当sbuf.st_uid也等于0时才能执行文件读取,实际返回1000。变量sbuf.st_uid表示文件所属用户的UID。 •修改crontab file文件的UID和GID都是0,chown 0:0 /var/spool/cron/crontabs/root; •重新启动crond:crond -f var/spool/cron/crontabs/ •10min后在/var/log/message里看到任务计划执行痕迹 Jan 10 12:00:00 (none) cron.info crond[854]: USER root pid 3506 cmd /usr/bin/compresslog.shJan 10 12:00:00 (none) cron.info crond[854]: USER root pid 3508 cmd /usr/local/bin/recode_check.shJan 10 12:10:00 (none) cron.info crond[854]: USER root pid 5007 cmd /usr/local/bin/recode_check.shJan 10 12:20:00 (none) cron.info crond[854]: USER root pid 6506 cmd /usr/local/bin/recode_check.sh 结果:修改“crontab file所属用户”有效,任务计划可以正常运行。 证明:“crontab file所属用户不合法”是诱因 4. 推断过程  看到这个1000我已经觉察到问题根本原因,看我娓娓道来。 /etc/passwd记录linux用户所属UID、GID。UID=0、GID=0属于root用户。passwd有若干ID号,普通预设的用户的UID、GID在1~999,adduser创建的用户ID从1000开始,启动crond守护进程时会根据当前用名去 /var/spool/cron/crontabs/ 目录下寻找与用户名同名的文件,顺带检查该文件的所属用户UID,只有文件存在、UID相同才读取该文件。 按照设想,那么crontab -e执行后应该会修改用户所属ID,下面是实验步骤。 再修改用户组为 1000 “chown 1000:root /var/spool/cron/crontabs/root” 观察crontab -e执行前后文件所属用户是否改变 实践和设想一致:crontab会修改文件所属用户。 5. 为什么测试阶段没发现问题 我的Linux系统开发环境普通用户编码从1000开始,为避免使用root用户误操作危害开发环境,一切文件均在普通用户环境下编辑,为有编辑权限,曾执行过 chown up /var/spool/cron/crontabs/root(不理解cron设计者为什么要去检查文件所属UID,即使当前已经是root权限),这个up就是我的用户名,up的UID=1000。 之所以在软件测试阶段未发现问题,原因在于任务计划默认10min才执行一次,为缩短测试时间而修改任务计划执行频率,提高测试效率,修改方法就是crontab -e编辑 /var/spool/cron/crontabs/root。 当初只注重recode_check.sh执行的正确性。

    时间:2021-03-15 关键词: crontab 定时任务 Linux

  • 分享功能强大的Linux全能系统实时监控利器

    dstat 是一款生成Linux系统资源统计信息的功能强大、灵活和通用的工具,可以替代vmstat,iostat,netstat和ifstat这些命令的多功能产品。dstat克服了这些命令的局限并增加了一些另外的功能,增加了监控项,也变得更灵活了。dstat可以很方便监控系统运行状况并用于基准测试和排除故障。拥有Python知识的用户可以构建他们自己的插件。 dstat将以列表的形式为你提供选项信息并清晰地告诉你是在何种幅度和单位显示输出。这样更好地避免了信息混乱和误报。更重要的是,它可以让你更容易编写插件来收集你想要的数据信息,以从未有过的方式进行扩展。 特性 安装方法 本地软件库中有相关安装包,你可以用下面命令安装: RHEL/Centos和Fedora系统: # yum install dstat 相关软件包在社区资源库中,你可以用这个命令来安装: 使用方法 这是默认输出显示的信息: CPU状态:CPU的使用率。这项报告更有趣的部分是显示了用户,系统和空闲部分,这更好地分析了CPU当前的使用状况。如果你看到"wait"一栏中,CPU的状态是一个高使用率值,那说明系统存在一些其它问题。当CPU的状态处在"waits"时,那是因为它正在等待I/O设备(例如内存,磁盘或者网络)的响应而且还没有收到。 网络统计(net):网络设备发送和接受的数据,这一栏显示的网络收、发数据总数。 系统统计(system):这一项显示的是中断(int)和上下文切换(csw)。这项统计仅在有比较基线时才有意义。这一栏中较高的统计值通常表示大量的进程造成拥塞,需要对CPU进行关注。你的服务器一般情况下都会运行运行一些程序,所以这项总是显示一些数值。 需要注意的是报告的第一行,通常这里所有的统计都不显示数值的。 但是dstat可以通过传递2个参数运行来控制报告间隔和报告数量。例如,如果你想要dstat输出默认监控、报表输出的时间间隔为3秒钟,并且报表中输出10个结果,你可以运行如下命令: -c:显示CPU系统占用,用户占用,空闲,等待,中断,软件中断等信息。 -d:显示磁盘读写数据大小。 -n:显示网络状态。 -l:显示系统负载情况。 -g:显示页面使用情况。 -s:显示交换分区使用情况。 -r:I/O请求情况。 --ipc:显示ipc消息队列,信号等信息。 -a:此为默认选项,等同于-cdngy。 --output 文件:此选项也比较有用,可以把状态信息以csv的格式重定向到指定的文件中,以便日后查看。例:dstat --output /root/dstat.csv & 此时让程序默默的在后台运行并把结果输出到/root/dstat.csv文件中。 当然不止这些用法,dstat附带了一些插件很大程度地扩展了它的功能。你可以通过查看/usr/share/dstat目录来查看它们的一些使用方法,常用的有这些: -–freespace :显示当前磁盘空间使用率 在运行的程序数量 -–top-cpu :图形化显示CPU占用最大的进程 -–top-mem :显示占用最多内存的进程 查看全部内存都有谁在占用: # dstat -c -y -l --proc-count --top-cpu 您可以将多个内部dstat插件与外部dstat插件一起使用,以查看所有可用插件的列表,请运行以下命令: dstat命令是一个用来替换vmstat、iostat、netstat、nfsstat和ifstat这些命令的工具,是一个全能系统信息统计工具。

    时间:2021-03-08 关键词: 实时监控 dstat Linux

  • 实用工具 | Linux下分屏终端

    sudo apt-get install terminator 一个窗口创建多个终端: 常用快捷键:

    时间:2021-03-03 关键词: 终端模拟器 Terminator Linux

  • ​“永远不被linux执行的程序”

    ​“永远不被linux执行的程序”

    1. 前言 “我的人品有这么差吗!半个小时Linux都没调度我的线程!”。 前些日子同事抱怨,“linux是多线程系统,每个线程都有一个时间片,为什么我的程序似乎一直没被调度”,随即给我演示执行过程。大致归纳成下面的代码逻辑。 程序启动后仅仅输出一行“run”,然后就没有然后了,喝着咖啡、嗑着瓜子、带薪摸鱼,屏幕上干干净净。理想状态下每10秒执行任务完毕后输出“do”。 分析代码逻辑可知 “推断” 代码是否被运行的依据是屏幕上输出 “do” ,”而这真的科学吗?答案是否定的,linux有着雨露均沾的调度系统,很难做到半小时没被调度。问题就出在linux的 “行缓冲”机制 。 void main(){ printf("run\n"); while(1) { sleep(10); do_thing(); printf("do"); }} 2. 行缓冲 上文的printf输出目标设备由STDOUT指定,STDOUT可能指向115200波特率的串口设备,也可能指向本地图形设备,相对于CPU而言他们的速度要慢上几个数量级。都是为了提高机器或者程序的性能、提高CPU利用率。协调高速设备和低速设备之间速度的不匹配,操作系统默认在标准I/O上采用行缓冲机制,printf的内容首先存储在内存,当缓冲填满或检测到换行符’’时则输出到目标设备。 Linux上这个行缓冲默认是1024Byte,每10s输出do占用2Byte,为了等待缓冲填满需要等待81min。 知道原理后解决方法就简单了。 方法1:fflush强制刷新标准输出stdout #include void main(){ printf("run\n"); while(1) { sleep(10); do_thing(); fflush(stdout); printf("do"); }} 方法2:输出“换行符” #include void main(){ printf("run\n"); while(1) { sleep(10); do_thing(); printf("do\n"); }}

    时间:2021-03-03 关键词: 线程 Linux

  • 如何通过程序执行shell命令并获取命令执行结果?

    如何通过程序执行shell命令并获取命令执行结果?

    时间:2021-03-01 关键词: shell Linux

  • 首个开源Linux系统登陆火星,一同登录的还有一款安卓手机芯片

    来源 | 量子位 作者 | 贾浩楠 萧箫 “确认着陆!毅力号安全到达火星表面。” 就在2月21日凌晨4点55分,美国“毅力号”不经变轨,直接冲入火星大气层,最终成功着陆。 “毅力号”成功着陆后,很快传回了首张图片。 这是美国自2012年以来,再一次以“空中吊车”的方式成功着陆火星,还给火星“带”来了首个开源Linux系统以及飞行软件框架F Prime。 F Prime装在名为“机智号”的无人机上,由毅力号携带到火星。 这也是直升机技术在地球外的首次使用。 值得一提的是,“机智号”上面,搭载的是高通骁龙Robotics Flight 801平台。 其实它的核心就是2014年旗舰手机上的高通骁龙801芯片,与小米4同款(7年前用过的手机SoC现在登陆火星了)。 “空中吊车”式着陆 与“好奇号”相似,这一次“毅力号”同样以“空中吊车”(sky crane)的方式着陆火星。 这种方案,会将着陆器分成两部分,上部分是一个空中吊车,自带8个强力反推火箭,下部分则是火星车。 从保护罩中被释放后,“毅力号”火星车将被吊车悬挂,通过尼龙绳和负责信号、控制指令传输的电缆,连接“吊车”并报告实时状态。 吊车稳定接触地表后,将瞬间切断尼龙绳和电缆,并用尽所有能量飞离“毅力号”火星车、并坠毁。 这次,“毅力号”在降落过程中,采用了2项新技术。 其一,为了尽可能降低着陆过程中的风险,在降落过程中,“毅力号”会快速拍照,通过距离触发技术,评估与火星地面的距离。 期间,“毅力号”被包裹在保护隔热罩中,在穿过大气层后,打开降落伞减速降落。 在这之后,隔热罩就会飞离,与吊车和火星车分开。 接下来,将采用第二项技术,即地形相对导航技术。系统利用这一技术,将着陆器拍的照片与机载地图相比较,确定着陆区环境,避开危险地形。 这次,“毅力号”降落的地点“耶泽罗陨击坑”(Jezero crater)附近散布着巨石、悬崖和沙丘,地势较为严峻。 但通过地形相对导航技术,吊车凭借点燃的8个反推火箭,引导“毅力号”避开了危险区域,最终成功着陆。 这次,毅力号还携带了两个麦克风(也是麦克风第一次被送上火星),来倾听火星上的声音。 这次将完成什么任务? 这次,“毅力号”火星车带来了7台重要仪器。 包括全景相机、激光测距仪、X射线光谱仪、紫外光谱仪、制氧器、气象观测设备、雷达等等。 这次它的主要任务,首先在着陆的火星远古湖泊地形中寻找生命可能存在的证据。 第二项任务,是采集火星地表土壤和岩石样本,并就地封存,等待今后NASA的火星任务将它取回来。 其它两项任务,包括探索着陆区域的地质多样性、为未来的火星任务验证新技术,这其中就包括了无人机的首飞实验,以及为登录火星的宇航员制备氧气。 火星首飞无人机,有什么黑科技? 重达一吨的毅力号火星车,史无前例的巨大和复杂,搭载了近十种科学仪器和探测设备。 但是,即使如此,火星车仍然有很大的局限,难以满足人类探索的好奇心。 首先是受制于火星严酷的环境条件(平均-63℃),火星车的移动速度十分缓慢。 人们最为熟知的“好奇号”迄今为止已运行了八年多,才累积行驶了22公里,平均速度还没有蜗牛快。 其次是火星车“越野”能力不足,无法进入山谷、坑道、悬崖等复杂地形作业。 于是,NASA的研究人员就想了一个办法来扩展火星车的视野——无人机。 即将进行史上首次火星飞行的无人机机智号 (Ingenuity),藏在火星车腹舱内一起登陆。 第一次登陆火星的机智号并没有承担任何具体的科研任务。 它的主要使命,就是验证无人机在火星环境中的可行性,收集飞行和火星大气数据,为今后能真正执行任务的无人机迭代经验。 那么,人类首架火星无人机,要克服哪些地球上没有的困难,又有哪些黑科技和看点? 只有1%大气压也能飞 给火星车配一个无人机,其实这个点子不难想到,真正的难点在于:怎么让它飞起来? ‍‍ ‍‍火星表面的重力大约只有地球的1/3(38%),看起来似乎很容易起飞,但有一点非常致命:火星大气的密度只有地球的1%。 这相当于在地球上3万米以上的高空起飞,而目前的高原型无人机,也不过可以确保最高在6500米的海拔正常飞行。 除了大气密度低,火星上的音速也比地球低不少,只有240米每秒。 如果叶片的自旋末梢速度超过音速,就会引发强烈的颤振,所以要把叶片的转速限制在每秒40转之内。 限制转速,又要有足够升力,这就要求整个设备不能过重。 最终的方案是无人机全重1.8公斤,高0.5米。采用顶部安装两对碳纤维螺旋桨来提供动力,直径1.2米,设计转速可达每分钟2400转,功率350瓦。 测试阶段,NASA的JPL实验室准备了一个名叫“空间模拟器”的巨大房间,可以模拟无人机在离开地球之后可能面临的各种极端气温,以及火星大气、重力环境。 最终,机智号实现了在-90℃的模拟火星环境下正常工作,水平移动的速度为10米每秒,爬升速度为3米每秒。 实现基本功能后,无人机还有一个重要挑战,就是通信和控制。 但火星和地球距离有10光分左右,不可能实现实时控制。 注:光分,即光在真空中一分钟所行走的距离。 所以,研究团队设计了一个指令列表,预装在毅力号上,由火星车对无人机进行通信指挥。 所以,机智号不能离火星车太远,设计的4次飞行测试,范围都不超过50米,时间也在90秒之内。 飞行中,无人机会捕捉图像,而毅力号也有可能拍下一些机智号盘旋在空中的图像。 首架火星无人机,7年前手机同款芯片 你没看错,火星无人机上用的处理器,就是小米和其他很多普通民用手机的同款。 而且,还是7年前的旗舰手机小米4同款芯片——高通骁龙801(28nm制程)。 为什么选择民用产品? 最重要的原因是,无人机对实时数据处理要求更高,包括飞行时的姿态控制、图像处理等等任务,而火星车上搭载的成熟产品不能满足要求。 一般来说,为了保证航天任务的成功率,传统航天器使用的设备,都偏重成熟稳定型号。 比如好奇号火星车的电脑使用的 CPU 是PowerPC 750(150nm制程,最高主频200MHz),其他的硬件配置也很低。 但由于机智号本身是实验验证性质,NASA反倒愿意承担一些风险,特别允许项目组在市场上采购民用产品。 最终选定的骁龙801处理器,除了体积小、抗辐射指标达标之外,算力更是比毅力号火星车上的处理器高好几个数量级。 除了处理器,机智号无人机的导航设备,包括惯性测量单元IMU、激光测距仪等等设备,都是通过电商平台SparkFun购买的,而且它们都是普通的手机级硬件。 这些民用品能不能在火星上与航天军工产品一较高下,很快就会见分晓。 首个火星无人机代码,开源! NASA“一声炮响”,给火星送来了Linux系统「手动狗头」。 没错,成功着陆的毅力号火星车,第一次把Linux操作系统带上了火星。 之前的NASA的火星探测器,使用的是VxWorks商业操作系统。 使用Linux系统的设备,正是即将进行史上首次火星飞行的无人机机智号 (Ingenuity)。 而且,NASA的喷气推进实验室为火星无人机开发的Linux飞行控制系统,开源了。 现在,任何开发者都能在Github上下载NASA火星无人机“同款”代码,并用在自己的飞行器上。 随着美国“毅力号”着陆、并开始进行一系列任务的同时,我国的“天问一号”,也已经在进行着陆的准备。 天问一号怎么样了? 目前,天问一号已经于2月10号入轨,并计划于5月左右,实施火星车登陆任务。 与毅力号直接进行“空中吊车”着陆的方式不同,天问一号将采用动力下降进行着陆的方式,即火箭反推悬停降落技术。 就是说,反推火箭会一直工作,直到着陆器降落到火星表面。 相比于着陆器本身,这项技术需要的燃料罐和反推火箭体积更大,传感系统也都装在着陆器底部。 由于燃料罐和反推火箭没有办法在着陆前完成脱离,因此,需要着陆腿增大跨距,以提高着陆安全性。 这也是目前最安全的着陆方案,着陆后,着陆器将放出火星车。 天问一号携带的火星车,采用太阳能供电,设计寿命90天。 如果最终这辆火星车成功着陆并运行,将成为人类史上首个一次性完成“绕、落、巡”的火星探测器。 期待它在5月份的表现。 NASA火星无人机开源地址: https://github.com/nasa/fprime 参考链接: https://www.wired.com/story/nasa-lands-the-perseverance-rover-on-mars/ https://www.nature.com/articles/d41586-021-00432-1 https://arstechnica.com/science/2021/02/what-to-expect-from-the-dramatic-mars-perseverance-landing-on-thursday/ https://spectrum.ieee.org/automaton/aerospace/robotic-exploration/nasa-designed-perseverance-helicopter-rover-fly-autonomously-mars https://www.futurezone.de/science/article216775269/Der-Mars-Hubschrauber-funktioniert-die-NASA-hats-bewiesen.html ------------ END ------------

    时间:2021-02-26 关键词: 芯片 安卓 Linux

首页  上一页  1 2 3 4 5 6 7 8 9 10 下一页 尾页
发布文章

技术子站

更多

项目外包