首页
关于
友链
其它
统计
壁纸
Search
1
修改Linux Kernel defconfig的标准方法
5,642 阅读
2
cgroup--(4)cgroup v1和cgroup v2的详细介绍
5,191 阅读
3
Android系统之VINTF(1)manifests&compatibility matrices
5,105 阅读
4
c语言的__attribute__
3,004 阅读
5
使用git生成patch和应用patch
2,431 阅读
默认分类
文章收集
学习总结
每天一刷
环境配置
知识点
入门系列
vim
shell
Git
Make
Android
Linux
Linux命令
内存管理
Linux驱动
Language
C++
C
工具
软件工具
Bug
COMPANY
登录
Search
标签搜索
shell
Linux
c
uboot
Vim
vintf
Linux驱动
Android
device_tree
git
DEBUG
链表
数据结构
IDR
内核
ELF
gcc
网址
内存管理
进程管理
adtxl
累计撰写
342
篇文章
累计收到
8
条评论
首页
栏目
默认分类
文章收集
学习总结
每天一刷
环境配置
知识点
入门系列
vim
shell
Git
Make
Android
Linux
Linux命令
内存管理
Linux驱动
Language
C++
C
工具
软件工具
Bug
COMPANY
页面
关于
友链
其它
统计
壁纸
搜索到
342
篇与
的结果
2020-08-12
Linux内核中链表list文件结构分析
1. 函数原型内核中的链表结构如下,只有前后两个指针,没有数据项,可以很方便的构成双向链表struct list_head { struct list_head *next, *prev; };1.1. static inline void INIT_LIST_HEAD(struct list_head *list)运行的时候初始化链表,两个指针都指向结点自己的地址static inline void INIT_LIST_HEAD(struct list_head *list) { WRITE_ONCE(list->next, list); list->prev = list; }1.2. static inline void list_add(struct list_head new, struct list_head head);从指定结点后面插入一个结点,new为要插入的新节点的地址,head为要插入的结点,新结点从head结点后面插入/** * list_add - add a new entry * @new: new entry to be added * @head: list head to add it after * * Insert a new entry after the specified head. * This is good for implementing stacks. */ static inline void list_add(struct list_head *new, struct list_head *head) { __list_add(new, head, head->next); }其中,__list_add()函数定义如下,在知道前后结点的情况下,插入结点/* * Insert a new entry between two known consecutive entries. * * This is only for internal list manipulation where we know * the prev/next entries already! */ static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) { if (!__list_add_valid(new, prev, next)) return; next->prev = new; new->next = next; new->prev = prev; WRITE_ONCE(prev->next, new); }1.3. static inline void list_add_tail(struct list_head new, struct list_head head)从链表尾部插入结点/** * list_add_tail - add a new entry * @new: new entry to be added * @head: list head to add it before * * Insert a new entry before the specified head. * This is useful for implementing queues. */ static inline void list_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); }1.4. static inline void list_del(struct list_head *entry)两个宏定义,删除下来的prev、next指针指向这两个特殊值,这样设置是为了保证不在链表中的结点项不可访问--对LIST_POISON1和LIST_POISON2的访问都将引起页故障。 /* * These are non-NULL pointers that will result in page faults * under normal circumstances, used to verify that nobody uses * non-initialized list entries. */ #define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA) #define LIST_POISON2 ((void *) 0x122 + POISON_POINTER_DELTA)static inline void list_del(struct list_head *entry) { __list_del_entry(entry); entry->next = LIST_POISON1; entry->prev = LIST_POISON2; }其中__list_del_entry()函数定义如下:/* * Delete a list entry by making the prev/next entries * point to each other. * * This is only for internal list manipulation where we know * the prev/next entries already! */ static inline void __list_del(struct list_head * prev, struct list_head * next) { next->prev = prev; WRITE_ONCE(prev->next, next); } /* * Delete a list entry and clear the 'prev' pointer. * * This is a special-purpose list clearing method used in the networking code * for lists allocated as per-cpu, where we don't want to incur the extra * WRITE_ONCE() overhead of a regular list_del_init(). The code that uses this * needs to check the node 'prev' pointer instead of calling list_empty(). */ static inline void __list_del_clearprev(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->prev = NULL; } /** * list_del - deletes entry from list. * @entry: the element to delete from the list. * Note: list_empty() on entry does not return true after this, the entry is * in an undefined state. */ static inline void __list_del_entry(struct list_head *entry) { if (!__list_del_entry_valid(entry)) return; __list_del(entry->prev, entry->next); }1.5. static inline void list_replace(struct list_head old,struct list_head new)替换链表中的结点,/** * list_replace - replace old entry by new one * @old : the element to be replaced * @new : the new element to insert * * If @old was empty, it will be overwritten. */ static inline void list_replace(struct list_head *old, struct list_head *new) { new->next = old->next; new->next->prev = new; new->prev = old->prev; new->prev->next = new; }1.6. static inline void list_replace_init(struct list_head old,struct list_head new)替换,将被替换的结点初始化为一个新链表static inline void list_replace_init(struct list_head *old, struct list_head *new) { list_replace(old, new); INIT_LIST_HEAD(old); }1.7. static inline void list_swap(struct list_head entry1,struct list_head entry2)交换两个结点/** * list_swap - replace entry1 with entry2 and re-add entry1 at entry2's position * @entry1: the location to place entry2 * @entry2: the location to place entry1 */ static inline void list_swap(struct list_head *entry1, struct list_head *entry2) { struct list_head *pos = entry2->prev; list_del(entry2); list_replace(entry1, entry2); if (pos == entry1) pos = entry2; list_add(entry1, pos); } 1.8. static inline void list_del_init(struct list_head *entry)删除一项并初始化/** * list_del_init - deletes entry from list and reinitialize it. * @entry: the element to delete from the list. */ static inline void list_del_init(struct list_head *entry) { __list_del_entry(entry); INIT_LIST_HEAD(entry); }1.9. static inline void list_move(struct list_head list, struct list_head head)搬移操作,将原本属于链表的一个结点移动到另一个链表的操作/** * list_move - delete from one list and add as another's head * @list: the entry to move * @head: the head that will precede our entry */ static inline void list_move(struct list_head *list, struct list_head *head) { __list_del_entry(list); list_add(list, head); }1.10. static inline void list_move_tail(struct list_head list,struct list_head head)/** * list_move_tail - delete from one list and add as another's tail * @list: the entry to move * @head: the head that will follow our entry */ static inline void list_move_tail(struct list_head *list, struct list_head *head) { __list_del_entry(list); list_add_tail(list, head); }1.11. static inline void list_bulk_move_tail(struct list_head head, struct list_head first, struct list_head *last)/** * list_bulk_move_tail - move a subsection of a list to its tail * @head: the head that will follow our entry * @first: first entry to move * @last: last entry to move, can be the same as first * * Move all entries between @first and including @last before @head. * All three entries must belong to the same linked list. */ static inline void list_bulk_move_tail(struct list_head *head, struct list_head *first, struct list_head *last) { first->prev->next = last->next; last->next->prev = first->prev; head->prev->next = first; first->prev = head->prev; last->next = head; head->prev = last; } 1.12. static inline int list_is_first(const struct list_head list,const struct list_head head)判断结点是否为首结点/** * list_is_first -- tests whether @list is the first entry in list @head * @list: the entry to test * @head: the head of the list */ static inline int list_is_first(const struct list_head *list, const struct list_head *head) { return list->prev == head; }1.13. static inline int list_is_last(const struct list_head list, const struct list_head head)判断结点是否为尾结点/** * list_is_last - tests whether @list is the last entry in list @head * @list: the entry to test * @head: the head of the list */ static inline int list_is_last(const struct list_head *list, const struct list_head *head) { return list->next == head; }1.14. static inline int list_empty(const struct list_head *head)判断是否是一个空链表/** * list_empty - tests whether a list is empty * @head: the list to test. */ static inline int list_empty(const struct list_head *head) { return READ_ONCE(head->next) == head; }1.15. static inline int list_empty_careful(const struct list_head *head)/** * list_empty_careful - tests whether a list is empty and not being modified * @head: the list to test * * Description: * tests whether a list is empty _and_ checks that no other CPU might be * in the process of modifying either member (next or prev) * * NOTE: using list_empty_careful() without synchronization * can only be safe if the only activity that can happen * to the list entry is list_del_init(). Eg. it cannot be used * if another CPU could re-list_add() it. */ static inline int list_empty_careful(const struct list_head *head) { struct list_head *next = head->next; return (next == head) && (next == head->prev); }1.16. static inline void list_rotate_left(struct list_head *head)翻转链表/** * list_rotate_left - rotate the list to the left * @head: the head of the list */ static inline void list_rotate_left(struct list_head *head) { struct list_head *first; if (!list_empty(head)) { first = head->next; list_move_tail(first, head); } } 1.17. static inline void list_rotate_to_front(struct list_head list,struct list_head head)/** * list_rotate_to_front() - Rotate list to specific item. * @list: The desired new front of the list. * @head: The head of the list. * * Rotates list so that @list becomes the new front of the list. */ static inline void list_rotate_to_front(struct list_head *list, struct list_head *head) { /* * Deletes the list head from the list denoted by @head and * places it as the tail of @list, this effectively rotates the * list so that @list is at the front. */ list_move_tail(head, list); }1.18. static inline int list_is_singular(const struct list_head *head)判断一个链表是否只有一项/** * list_is_singular - tests whether a list has just one entry. * @head: the list to test. */ static inline int list_is_singular(const struct list_head *head) { return !list_empty(head) && (head->next == head->prev); } 1.19. static inline void list_cut_position(struct list_head list,struct list_head head, struct list_head *entry)将一个链表拆分为两个/** * list_cut_position - cut a list into two * @list: a new list to add all removed entries * @head: a list with entries * @entry: an entry within head, could be the head itself * and if so we won't cut the list * * This helper moves the initial part of @head, up to and * including @entry, from @head to @list. You should * pass on @entry an element you know is on @head. @list * should be an empty list or a list you do not care about * losing its data. * */ static inline void list_cut_position(struct list_head *list, struct list_head *head, struct list_head *entry) { if (list_empty(head)) return; if (list_is_singular(head) && (head->next != entry && head != entry)) return; if (entry == head) INIT_LIST_HEAD(list); else __list_cut_position(list, head, entry); }1.20. static inline void list_cut_before(struct list_head list,struct list_head head,struct list_head *entry)/** * list_cut_before - cut a list into two, before given entry * @list: a new list to add all removed entries * @head: a list with entries * @entry: an entry within head, could be the head itself * * This helper moves the initial part of @head, up to but * excluding @entry, from @head to @list. You should pass * in @entry an element you know is on @head. @list should * be an empty list or a list you do not care about losing * its data. * If @entry == @head, all entries on @head are moved to * @list. */ static inline void list_cut_before(struct list_head *list, struct list_head *head, struct list_head *entry) { if (head->next == entry) { INIT_LIST_HEAD(list); return; } list->next = head->next; list->next->prev = list; list->prev = entry->prev; list->prev->next = list; head->next = entry; entry->prev = head; }1.21. static inline void list_splice(const struct list_head list,struct list_head head)连接两个链表/** * list_splice - join two lists, this is designed for stacks * @list: the new list to add. * @head: the place to add it in the first list. */ static inline void list_splice(const struct list_head *list, struct list_head *head) { if (!list_empty(list)) __list_splice(list, head, head->next); }1.22. static inline void list_splice_tail(struct list_head list,struct list_head head)/** * list_splice_tail - join two lists, each list being a queue * @list: the new list to add. * @head: the place to add it in the first list. */ static inline void list_splice_tail(struct list_head *list, struct list_head *head) { if (!list_empty(list)) __list_splice(list, head->prev, head); }1.23. static inline void list_splice_init(struct list_head list, struct list_head head)/** * list_splice_init - join two lists and reinitialise the emptied list. * @list: the new list to add. * @head: the place to add it in the first list. * * The list at @list is reinitialised */ static inline void list_splice_init(struct list_head *list, struct list_head *head) { if (!list_empty(list)) { __list_splice(list, head, head->next); INIT_LIST_HEAD(list); } }1.24. static inline void list_splice_tail_init(struct list_head list, struct list_head head)/** * list_splice_tail_init - join two lists and reinitialise the emptied list * @list: the new list to add. * @head: the place to add it in the first list. * * Each of the lists is a queue. * The list at @list is reinitialised */ static inline void list_splice_tail_init(struct list_head *list, struct list_head *head) { if (!list_empty(list)) { __list_splice(list, head->prev, head); INIT_LIST_HEAD(list); } }2. 使用的宏定义2.1. LIST_HEAD_INIT#define LIST_HEAD_INIT(name) { &(name), &(name) }2.2. LIST_HEAD#define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) 2.3. list_entry#define list_entry(ptr, type, member) \ container_of(ptr, type, member)2.4. list_first_entry#define list_first_entry(ptr, type, member) \ list_entry((ptr)->next, type, member)2.5. list_last_entry#define list_last_entry(ptr, type, member) \ list_entry((ptr)->prev, type, member)2.6. list_first_entry_or_null#define list_first_entry_or_null(ptr, type, member) ({ \ struct list_head *head__ = (ptr); \ struct list_head *pos__ = READ_ONCE(head__->next); \ pos__ != head__ ? list_entry(pos__, type, member) : NULL; \ })2.7. list_next_entry#define list_next_entry(pos, member) \ list_entry((pos)->member.next, typeof(*(pos)), member)2.8. list_prev_entry#define list_prev_entry(pos, member) \ list_entry((pos)->member.prev, typeof(*(pos)), member)2.9. list_for_each#define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next)2.10. list_for_each_prev#define list_for_each_prev(pos, head) \ for (pos = (head)->prev; pos != (head); pos = pos->prev)2.11. list_for_each_safe#define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next)2.12. list_for_each_prev_safe#define list_for_each_prev_safe(pos, n, head) \ for (pos = (head)->prev, n = pos->prev; \ pos != (head); \ pos = n, n = pos->prev)2.13. list_for_each_entry#define list_for_each_entry(pos, head, member) \ for (pos = list_first_entry(head, typeof(*pos), member); \ &pos->member != (head); \ pos = list_next_entry(pos, member))2.14. list_for_each_entry_reverse#define list_for_each_entry_reverse(pos, head, member) \ for (pos = list_last_entry(head, typeof(*pos), member); \ &pos->member != (head); \ pos = list_prev_entry(pos, member))2.15. list_prepare_entry#define list_prepare_entry(pos, head, member) \ ((pos) ? : list_entry(head, typeof(*pos), member))2.16. list_for_each_entry_continue#define list_for_each_entry_continue(pos, head, member) \ for (pos = list_next_entry(pos, member); \ &pos->member != (head); \ pos = list_next_entry(pos, member))2.17. list_for_each_entry_from_reverse#define list_for_each_entry_from_reverse(pos, head, member) \ for (; &pos->member != (head); \ pos = list_prev_entry(pos, member))2.18. list_for_each_entry_safe#define list_for_each_entry_safe(pos, n, head, member) \ for (pos = list_first_entry(head, typeof(*pos), member), \ n = list_next_entry(pos, member); \ &pos->member != (head); \ pos = n, n = list_next_entry(n, member))2.19. list_for_each_entry_safe_continue#define list_for_each_entry_safe_continue(pos, n, head, member) \ for (pos = list_next_entry(pos, member), \ n = list_next_entry(pos, member); \ &pos->member != (head); \ pos = n, n = list_next_entry(n, member))2.20. list_for_each_entry_safe_from#define list_for_each_entry_safe_from(pos, n, head, member) \ for (n = list_next_entry(pos, member); \ &pos->member != (head); \ pos = n, n = list_next_entry(n, member))2.21. list_for_each_entry_safe_reverse#define list_for_each_entry_safe_reverse(pos, n, head, member) \ for (pos = list_last_entry(head, typeof(*pos), member), \ n = list_prev_entry(pos, member); \ &pos->member != (head); \ pos = n, n = list_prev_entry(n, member))2.22. list_safe_reset_next#define list_safe_reset_next(pos, n, member) \ n = list_next_entry(pos, member)
2020年08月12日
815 阅读
0 评论
0 点赞
2020-08-10
Linux-系统操作
1.帮助命令manman是manual的缩写用法: man 命令man 也是一条命令,分为9章,可以使用man命令获得man的帮助,如man 7 manhelp内部命令使用help帮助,help 命令外部命令使用help帮助,命令 --help使用type 命令可以查看是内部命令还是外部命令infoinfo帮助比help更详细2.文件命令pwd命令显示当前目录的绝对路径ls命令查看当前目录下的文件基本语法:ls [选项,选型] 参数......常用选项-l 长格式显示文件-a 显示隐藏文件-r 逆序显示-t 按照时间顺序显示-R 递归显示cd命令更改当前的操作目录常用操作:cd - :返回上一目录mkdir命令建立目录常用选项:-p 建立多级目录rmdir命令删除空目录cp命令复制文件和目录基本语法:cp [选项] 文件路径cp [选项] 文件... 路径常用选项:-r 复制目录,不加选项只能复制文件-p 复制时保留用户、权限、时间等文件属性-a 等同于-dpR,显示复制过程mv命令移动或者重命名文件基本语法:mv [选项] 源文件 目标文件mv [选项] 源文件 目录rm命令删除文件常用选项:-r 删除目录,非空的-f 删除文件不进行提示通配符定义:shell 内建的符号用途:操作多个相似的文件常用的通配符:* 匹配任何字符串? 匹配一个字符串[xyz] 匹配xyz任意一个字符[a-z] 匹配一个范围[!xyz] 不匹配3. 文本查看命令cat 文本内容显示到终端head 查看文件开头tail 查看文件结尾常用参数:-f 文件内容更新后,显示信息同步更新wc 统计文件内容信息moreless4.打包与压缩命令打包命令tar命令是Linux中的备份命令,在打包完成后,需要对文件进行压缩,压缩的命令是gzip和bzip2.经常使用的扩展名是.tar.gz .tar.bz2 .tgz .tbz2常用选项: c 打包x 解包f 指定操作类型为文件压缩和解压缩可以先使用tar命令打包,再单独使用命令gzip和bzip2命令。但在日常的使用中,通常和tar命令配合使用常用选项:-z: gzip格式压缩和解压缩-j: bzip2格式压缩和解压缩5.Vi编辑器进入vim后即为正常模式,可以复制粘贴。按i进入插入模式,可以进行文本的输入。从插入模式退出,按ESC进入正常模式,然后输入:或者\进入命令模式,在命令行下输入:wq,:q可退出。正常模式进入其他模式的转换命令i 进入插入模式v 进入可视化模式: 进入命令模式esc 从其他模式回到正常模式基本操作:使用h j k l控制上下左右的移动,一些基本操作y 复制一般都是按行复制,使用yy命令,使用数字加yy可以复制多行,使用y$可以复制从光标到行尾全部内容d 剪切dd剪切一整行p 粘贴u 撤销ctrl+r 重做,把撤销指令重做x 删除单个字符r 替换单个字符G 定位指定的行数字加G定位到指定行^ 定位到行首$ 定位到行尾命令模式:w 写入:q 退出:! 执行shell命令:s 替换使用方法s/old/new,只是用s只替换光标所在行的内容,使用%s可替换所有行的第一个字符。使用%s/old/new/g可以替换所有,global3,5s/old/new是指替换3到5行的/ 查找使用n查看下一个查找到的内容,使用shift+n查看上一个:set 设置命令:set nu, :set nonu可视模式进入可视模式的方式v 字符可视模式V 行可视模式ctrl+v 块可视化模式6.用户和用户组管理及密码管理用户管理常用命令useradd 新建用户useradd 用户名用户是否存在,使用 id 用户名 可以知道用户是否存在userdel 删除用户userdel 用户名即可删除用户,但会保留用户的家目录使用-r参数可以删除用户目录passwd 修改用户密码usermod 修改用户属性可以修改用户家目录、用户组等信息chage 修改用户属性可以修改用户的生命周期用户组管理命令groupadd 新建用户组groupdel 删除用户组su和sudo命令su 切换用户su - USERNAMEsudo 以其他用户身份执行命令visudo 设置需要使用sudo的用户(组)用户和用户组配置文件/etc/passwd/ /etc/shadow//etc/group/7.文件权限文件类型:- 普通文件 d 目录文件b 块特殊文件c 字符特殊文件l 符号链接(类似Windows快捷方式)f 命名管道s 套接字文件文件权限的表示字符权限的表示法:r 读w 写x 执行数字权限的表示法:r = 4w = 2x = 1如 rw-r-xr--意为rw- 文件属主的权限r-x 文件属组的权限r-- 其它用户的权限文件权限的修改root用户权限不受限chmod 更该文件、目录权限字符表示法:u g o a参数表示用户属主、属组、其他用户、和全部u=x,u+x,u-x设置、增加、减少权限chmod u+x /tmp/testfile数字表示法:chmod 755 /tmp/testfilechown 更改属主、属组chgrp 可以单独改属组,不常用使用ctrl+r,可以查找历史命令
2020年08月10日
766 阅读
0 评论
0 点赞
1
...
34
35