Linux守护进程 2015年09月30日 linux

    守护进程一般在系统启动的时候启动,在系统关闭的时候才会退出, Linux的大多数服务器都是以守护进程的形式实现。因为在后台运行,也叫后台进程,独立于终端运行,故输出需要特殊处理。

    守护进程的父进程是init进程,因为其真正父进程在fork()出子进程就立即退出了,将子进程交给init托管。

    进程组
    每个进程的进程组ID就是组长的ID,进程只能为自己或其子进程设置组ID。
    会话
    新建会话的目的主要是解除原有的会话,另一方面因为如果该进程是组长,就无法建立新会话,所以要先fork()一个子进程。

    编写守护进程需要完成如下步骤:

    1. 父进程fork()并退出。
    2. 子进程umask(0)
    3. 子进程setsid()创建新会话。
    4. 子进程chdir("/")切换工作目录,如果不切换工作目录可能导致进程占用文件系统,使文件系统无法卸载。
    5. 子进程关闭所有不用的文件描述符。

    Linux IO操作 2015年09月29日 linux

    除了最基本的读写操作之外,Linux还提供了一些高级特征。非阻塞的IO操作允许在文件未准备好的情况下直接返回错误。记录锁让文件的一个区域锁住,防止被其它人篡改。 IO多路复用允许我们同时查询多个文件中哪些已经准备好。异步IO则可以通过异步IO控制块进行异步传输。分散聚集读写操作允许我们将连续的读写操作分割成多个读写操作同时发送出去。固定长度读写让我们能够准确读取指定数目的长度,这实际上是多次调用读写来实现。内存映射可以让我们像访问内存一样的方式来修改文件。

    Linux多线程 2015年09月28日 linux

    进程可以看作单个线程,多线程就是在一个进程中开启多个运行线程,每个进程使用各自的内存地址空间和文件描述符,但是线程不一样,同一进程下开启的线程自动继承相同的地址空间和文件描述符。

    Linux下有一个遵循POSIX.1-2001的线程接口,叫pthread。线程也有线程ID,叫TID。创建线程用如下函数。

    int pthread_create(pthread_t *restrict tidp,
                       const pthread_attr_t *restrict attr,
                       void *(*thread_func)(void *), void *restrict arg);
    
    tidp
    用于保存创建线程的TID
    attr
    用于设置线程的属性,可以传递NULL
    thread_func
    即是当作线程执行的函数,线程继承地址空间和信号mask,但是pending信号被清除
    arg
    即thread_func的参数

    Linux DMA-BUF 2015年09月28日 kernel

    如果设备驱动想要共享DMA缓冲区,可以让一个驱动来导出,一个驱动来使用。类似于消费者生产者模型,Linux DMA-BUF就是基于这种方式来实现的。

    Linux内核中的DMA BUF这部分代码主要由Sumit Semwal贡献,可以在Linux内核源码树目录下执行如下命令查看相关提交。

    git log --author="Sumit Semwal"
    

    生产者要完成的工作:

    • 实现对缓冲区的管理操作
    • 允许使用者通过dma_buf共享接口来共享内存
    • 管理内存分配的细节
    • 决定实际的存储位置
    • 管理散列表迁移

    使用者的好处:

    • 可以有很多使用者共用这部分内存
    • 不需要关心怎样分配,以及分配在何处
    • 需要一个入口去访问散列表,以映射到自己的地址空间

    C语言单元测试 2015年09月25日 language

    CUnit是一个轻量级的系统,用于对C代码进行单元测试, CUnit以静态库的方式提供给用户使用。

    主要头文件如下。

    CUnit/CUnit.h
    主要包括用于测试的宏
    CUnit/CUError.h
    错误处理函数和数据类型
    CUnit/TestDB.h
    用于registry、suites和tests
    CUnit/TestRun.h
    运行测试和生成结果
    CUnit/Automated.h
    用于输出xml
    CUnit/Basic.h
    非交互式输出到stdout的接口
    CUnit/Console.h
    交互式console接口
    CUnit/CUCurses.h
    交互式console接口(*nix)
    CUnit/Win.h
    Windows接口

    C/C++中的字符串 2015年09月25日 language

    C语言的字符串很好理解,本身是一个数组,只不过对字符串的最后一个元素有特别的要求,最后一个元素必须是null。但是C语言也提供了一系列的库函数来操作字符串,避免自己去实现相关的操作。

    MTD设备简介 2015年09月22日 linux

    闪存的好处是无噪音,寻址快,低功耗。但是也有缺点,对于同一个block必须在每次写入前对整个block进行擦除,因此称之为erase block。并且闪存的擦除次数是有限的,最多也就百万次,为了增加闪存寿命,就必须要使得每个地方均匀擦除,防止个别地方擦除次数太多。 NOR flash允许随机逐字节访问,因此CPU可以直接从NOR flash执行代码,对于bootloader来说非常好,不必复制到内存就能执行。而目前市面最流行的是NAND flash,因为价格更低,但是需要专门的控制器访问,所以不能直接从flash执行代码,有时候flash中有坏块,可以通过硬件或软件来识别和去除坏块。目前有两种NAND flash,一种仿真块设备接口,包含一个硬件FTL来维护erase block,像USB flash、EMMC、SSD属于此类,这样有助于降低OS的软件复杂度。另一种是裸flash,操作系统访问flash控制器,直接管理block,这种情况下就可以计算一个块的擦除次数。 Linux内核实现了一个MTD子系统,对访问flash设备提供了一个通用接口。

    正则表达式 2015年08月19日 language

    正则表达式被编译成字节码,然后用C编写的匹配引擎执行。元字符有其特殊含义,完整列表包括:. ^ $ * + ? { [ ] \ | ( )。中括号[]用来指定一个字符所属的字符集,如[abc][a-c]含义相同,比较重要的一点是元字符在字符集中会退化为普通字符,有两个例外,一个是放在首部的^字符,表示补集,另一个是转义字符。提到转义字符,它除了退化元字符的功能外,还能够转义普通字符以表示特殊字符集。

    转义序列 等价表达式 含义
    \d [0-9] 数字
    \D [^0-9] 非数字
    \s [ \t\n\r\f\v] 空白字符
    § [^ \t\n\r\f\v] 非空白字符
    \w [a-zA-Z0-9_] 字母数字
    \W [^a-zA-Z0-9_] 非字母数字
    \A   只匹配字符串首
    \Z   只匹配字符串尾
    \b   零宽界定符:单词边界
    \B   零宽界定符:非单词边界

    Python正则表达式 2015年08月19日 language

    正则表达式被编译成字节码,然后用C编写的匹配引擎执行。元字符有其特殊含义,完整列表包括:. ^ $ * + ? { [ ] \ | ( )。中括号[]用来指定一个字符所属的字符集,如[abc][a-c]含义相同,比较重要的一点是元字符在字符集中会退化为普通字符,有两个例外,一个是放在首部的^字符,表示补集,另一个是转义字符。提到转义字符,它除了退化元字符的功能外,还能够转义普通字符以表示特殊字符集。

    转义序列 等价表达式 含义
    \d [0-9] 数字
    \D [^0-9] 非数字
    \s [ \t\n\r\f\v] 空白字符
    § [^ \t\n\r\f\v] 非空白字符
    \w [a-zA-Z0-9_] 字母数字
    \W [^a-zA-Z0-9_] 非字母数字
    \A   只匹配字符串首
    \Z   只匹配字符串尾
    \b   零宽界定符:单词边界
    \B   零宽界定符:非单词边界

    Linux虚拟文件系统源码分析 2015年08月09日 kernel

    VFS中关联的数据结构很多,如下图所示。在这里我们先把核心要素说明一下,基本上都是按照面向对象的思路来设计的,而最重要的要素就是超级块、索引节点、文件和目录项。

    这里会介绍文件描述符到文件的转换,索引节点和目录项哈希表的基本操作,并以根文件系统为例说明文件系统的注册与挂载操作。此外还包括文件名查询代码的分析,以及文件访问操作等。