[linux内核][LINUX内核编程]学习笔记(二)

linux内核————队列

linux内核——队列

定义:

[cpp] view plaincopy

  1. struct __kfifo{
  2. unsigned int in;  //入队偏移,写索引
  3. unsigned int out;  //出队偏移,读索引
  4. unsigned int mask;
  5. unsigned int esize;
  6. void *data;
  7. }

使用:

创建一个队列,该函数创建并初始化一个大小为size的kfifo:

[cpp] view plaincopy

  1. 38 int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
  2. 39                 size_t esize, gfp_t gfp_mask)
  3. 40 {
  4. 45         size = roundup_pow_of_two(size);
  5. 46
  6. 47         fifo->in = 0;
  7. 48         fifo->out = 0;
  8. 49         fifo->esize = esize;
  9. 50
  10. 51         if (size < 2) {
  11. 52                 fifo->data = NULL;
  12. 53                 fifo->mask = 0;
  13. 54                 return -EINVAL;
  14. 55         }
  15. 56
  16. 57         fifo->data = kmalloc(size * esize, gfp_mask);
  17. 58
  18. 59         if (!fifo->data) {
  19. 60                 fifo->mask = 0;
  20. 61                 return -ENOMEM;
  21. 62         }
  22. 63         fifo->mask = size - 1;
  23. 64
  24. 65         return 0;
  25. 66 }

判断一个整数是否是2的整数次幂

[cpp] view plaincopy

  1. static inline int is_power_of_2(unsigned long long n)
  2. {
  3. return (n!=0 &&(n&(n-1)==0))
  4. }

推入数据到队列的方法是kfifo_in()函数

[cpp] view plaincopy

  1. 102 static void kfifo_copy_in(struct __kfifo *fifo, const void *src,
  2. 103                 unsigned int len, unsigned int off)
  3. 104 {
  4. 105         unsigned int size = fifo->mask + 1;
  5. 106         unsigned int esize = fifo->esize;
  6. 107         unsigned int l;
  7. 108
  8. 109         off &= fifo->mask;  //该操作从数学角度将就是对长度fifo->mask的取模运算
  9. 110         if (esize != 1) {
  10. 111                 off *= esize;
  11. 112                 size *= esize;
  12. 113                 len *= esize;
  13. 114         }
  14. 115         l = min(len, size - off);  //size-off代表的含义是当前in到缓冲区尾的大小,
  15. 116     /*
  16. 先从buffer中拷贝l字节到缓冲区剩余空间,l<=len,也<=从real_in开始到缓冲区结尾的空间
  17. 所以这个copy可能没拷贝完,但是不会造成缓冲区越界
  18. */
  19. 117         memcpy(fifo->data + off, src, l);
  20. /*
  21. len > l时,拷贝buffer中剩余的内容,其实地址当然为buffer + l,而剩余的大小为len - l
  22. 当len == l时,下面的memcpy啥都不干
  23. */
  24. 118         memcpy(fifo->data, src + l, len - l);
  25. 123         smp_wmb();
  26. 124 }
  27. 125
  28. 126 unsigned int __kfifo_in(struct __kfifo *fifo,
  29. 127                 const void *buf, unsigned int len)  //buf指向的是请求入队的缓冲区,len表示的是请求写入的大小
  30. 128 {
  31. 129         unsigned int l;
  32. 131         l = kfifo_unused(fifo);//计算队列中剩余空间的大小,fifo->size-(fifo->in-fifo->out)
  33. 132         if (len > l)
  34. 133                 len = l;
  35. 135         kfifo_copy_in(fifo, buf, len, fifo->in);
  36. 136         fifo->in += len;
  37. 137         return len;
  38. 138 }

kfifo的巧妙之处在于in和out定义为无符号类型,在put和get时,in和out都是增加,当达到最大值时,产生溢出,使得从0开始,进行循环使用

时间: 2024-07-31 10:54:47

[linux内核][LINUX内核编程]学习笔记(二)的相关文章

linux sheel编程学习笔记(二) --- grep命令

Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来.grep全称是Global Regular Expression Print,表示全局正则表达式版本,它的使用权限是所有用户. grep的工作方式是这样的,它在一个或多个文件中搜索字符串模板.如果模板包括空格,则必须被引用,模板后的所有字符串被看作文件名.搜索的结果被送到标准输出,不影响原文件内容. grep可用于shell脚本,因为grep通过返回一个状态值来说明搜索的状态,如果模板搜索成

FFmpeg编程学习笔记二:音频重采样

ffmpeg实现音频重采样的核心函数swr_convert功能非常强大,可是ffmpeg文档对它的注释太过简单,在应用中往往会出这样那样的问题,其实在读取数据->重采样->编码数据的循环中在第一次执行swr_convert后还应用swr_convert再作个缓存检测看看是否还有数据,如果有就要把它写到FIFO中去,留在下次再使用,这点在转码和由低向高转换采样率时特别重要. 下面一段简单的代码,摘自我自已写的测试程序. const int frame_size = FFMIN(fifo_size

linux网络编程学习笔记之二 -----错误异常处理和各种碎碎(更新中)

errno 在unix系统中对大部分系统调用非正常返回时,通常返回值为-1,并设置全局变量errno(errno.h),如socket(), bind(), accept(), listen().erron存放一个正整数来保存上次出错的错误值. 对线程而言,每个线程都有专用的errno变量,不必考虑同步问题. strerror converts to English (Note: use strerror_r for thread safety) perror is simplified str

linux网络编程学习笔记之六 -----I/O多路复用服务端

多进程和多线程的目的是在于最大限度地利用CPU资源,当某个进程不需要占用太多CPU资源,而是需要I/O资源时,可以采用I/O多路复用,基本思路是让内核把进程挂起,直到有I/O事件发生时,再把控制返回给程序.这种事件驱动模型的高效之处在于,省去了进程和线程上下文切换的开销.整个程序运行在单一的进程上下文中,所有的逻辑流共享整个进程的地址空间.缺点是,编码复杂,而且随着每个逻辑流并发粒度的减小,编码复杂度会继续上升. I/O多路复用典型应用场合(摘自UNP6.1) select的模型就是这样一个实现

Linux System Programming 学习笔记(二) 文件I/O

1.每个Linux进程都有一个最大打开文件数,默认情况下,最大值是1024 文件描述符不仅可以引用普通文件,也可以引用套接字socket,目录,管道(everything is a file) 默认情况下,子进程会获得其父进程文件表的完整拷贝 2.打开文件 open系统调用必须包含 O_RDONLY,O_WRONLY,O_RDWR 三种存取模式之一 注意 O_NONBLOCK模式 int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644

linux学习笔记二:linux文件系统

各大linux的版本都遵循着FHS(Filesystem Hierarchy Standard)文件系统目录标准,是一个树形结构的组织文件.在此简要记录各目录. linux下所有文件都处在/文件下. 树形结构图: /boot:  系统启动相关的文件 主要文件 1.vmliunx:内核    2.initramfs:磁盘映像文件   3.grub(bootloader) /dev:设备文件 块设备:随机访问设备. 字符设备:线性设备,顺序访问.按字符为单位.键盘.鼠标. 设备号:主设备号(majo

linux网络编程学习笔记之四 -----多线程并发服务端

相对于使用进程实现并发,用线程的实现更加轻量.每个线程都是独立的逻辑流.线程是CPU上独立调度运行的最小单位,而进程是资源分配的单位.当然这是在微内核的操作系统上说的,简言之这种操作系统的内核是只提供最基本的OS服务,更多参看点击打开链接 每个线程有它自己的线程上下文,包括一个唯一的线程ID(linux上实现为unsigned long),栈,栈指针,程序计数器.通用目的寄存器和条件码,还有自己的信号掩码和优先级.同一个进程里的线程共享这个进程的整个虚拟地址空间,包括可执行的程序文本.程序的全局

Linux Shell脚本编程学习笔记和实战

http://www.1987.name/141.html shell基础 终端打印.算术运算.常用变量 Linux下搜索指定目录下特定字符串并高亮显示匹配关键词 从键盘或文件中获取标准输入 [read命令] 文件的描述符和重定向 数组.关联数组和别名使用 函数的定义.执行.传参和递归函数 条件测试操作与流程控制语句 获取时间日期格式和延时 [date.sleep命令] 内部字段分隔符IFS和脚本的调试DEBUG 显示.读取或拼接文件内容 [cat命令] 文件查找与打印文件列表 [find命令]

Linux学习笔记二:Linux的文件处理命令

1.文件处理命令:ls 作用:显示目录文件 语法:ls [选项] [文件或目录] [选项]:-a 显示所有文件,包括隐藏文件   -l 显示详细信息 -d 查看目录属性 [文件或目录]:当省略时默认将当前路径作为参数 实例: · ls 显示当前文件夹下所有文件(不包括隐藏文件)的信息 · ls -l 显示当前文件夹下所有文件(不包括隐藏文件)的详细信息 · ls -ld  显示当前文件夹的详细信息 技巧:要查看文件夹的信息,必须加-d参数:要查看详细参数,必须加-l参数. 2.文件的属性 使用”

linux学习笔记二:硬盘信息查询

在linux管理中,硬盘管理是很重要的一部分.包括阵列,分区,逻辑卷等操作,在对硬盘操作前,需要充分的了解硬盘的信息.常用的硬盘查询有以下几种: 1.df  查看文件系统空间使用情况: linux-lszd-db:~ # dfFilesystem     1K-blocks     Used Available Use% Mounted on/dev/sda6      809262496 37615092 770825244   5% /udev             8076412