logo资料库

linux-sys.zh.pdf

第1页 / 共179页
第2页 / 共179页
第3页 / 共179页
第4页 / 共179页
第5页 / 共179页
第6页 / 共179页
第7页 / 共179页
第8页 / 共179页
资料共179页,剩余部分请下载后查看
前言
目录
1 文件I/O
1.1 C标准函数与系统函数的区别
1.1.1 I/O缓冲区
1.1.2 效率
1.1.3 程序的跨平台性
1.2 PCB概念
1.2.1 task_struct结构体
1.2.2 files_struct结构体
1.3 open/close
1.3.1 文件描述符
1.3.2 最大打开文件个数
1.4 read/write
1.5 阻塞和非阻塞
1.5.1 阻塞读终端
1.5.2 非阻塞读终端
1.5.3 非阻塞读终端和等待超时
1.6 lseek
1.7 fcntl
1.7.1 用fcntl改变File Status Flag
1.8 ioctl
1.9 习题
2 文件系统
2.1 ext2文件系统
2.1.1 目录中记录项文件类型
2.1.2 数据块寻址
2.2 stat
2.3 chmod
2.4 chown
2.5 utime
2.6 truncate
2.7 link
2.7.1 link
2.7.2 symlink
2.7.3 readlink
2.7.4 unlink
2.8 rename
2.9 chdir
2.10 getcwd
2.11 pathconf
2.12 目录操作
2.12.1 mkdir
2.12.2 rmdir
2.12.3 opendir/fdopendir
2.12.4 readdir
2.12.5 rewinddir
2.12.6 telldir/seekdir
2.12.7 closedir
2.12.8 递归遍历目录
2.13 VFS虚拟文件系统
2.13.1 dup/dup2
2.14 练习
3 进程
3.1 进程环境
3.2 进程状态
3.3 进程原语
3.3.1 fork
3.3.2 exec族
3.3.3 wait/waitpid
3.4 练习
4 进程间通信
4.1 pipe管道
4.2 fifo有名管道
4.3 内存共享映射
4.3.1 mmap/munmap
4.3.2 进程间共享通信
4.4 Unix Domain Socket
4.5 习题
5 信号
5.1 信号的概念
5.1.1 信号编号
5.1.2 信号机制
5.1.3 信号产生种类
5.1.4 信号产生原因
5.2 进程处理信号行为
5.3 信号集处理函数
5.4 PCB的信号集
5.4.1 sigprocmask
5.4.2 sigpending
5.5 信号捕捉设定
5.5.1 利用SIGUSR1和SIGUSR2实现父子进程同步输出
5.6 C标准库信号处理函数
5.6.1 signal
5.7 可重入函数
5.8 信号引起的竞态和异步I/O
5.8.1 时序竞态
5.8.2 全局变量异步I/O
5.8.3 可重入函数
5.8.4 避免异步I/O的类型
5.9 SIGCHLD信号处理
5.9.1 SIGCHLD的产生条件
5.9.2 status处理方式
5.10 向信号捕捉函数传参
5.10.1 sigqueue
5.10.2 sigaction
5.11 信号中断系统调用
5.12 练习
6 进程间关系
6.1 终端
6.1.1 网络终端
6.2 进程组
6.3 会话
7 守护进程
7.1 概念
7.2 模型
7.3 习题
8 线程
8.1 线程概念
8.1.1 什么是线程
8.1.2 线程和进程的关系
8.1.3 线程间共享资源
8.1.4 线程间非共享资源
8.1.5 线程优缺点
8.1.6 pthread manpage
8.2 线程原语
8.2.1 pthread_create
8.2.2 pthread_self
8.2.3 pthread_exit
8.2.4 pthread_join
8.2.5 pthread_cancel
8.2.6 pthread_detach
8.2.7 pthread_equal
8.3 线程终止方式
8.4 线程属性
8.4.1 线程属性初始化
8.4.2 线程的分离状态(detached state)
8.4.3 线程的栈地址(stack address)
8.4.4 线程的栈大小(stack size)
8.4.5 线程属性控制实例
8.5 NPTL
8.6 细节注意
8.7 练习
9 线程同步
9.1 线程为什么要同步
9.2 互斥量
9.2.1 临界区(Critical Section)
9.2.2 临界区的选定
9.2.3 互斥量实例
9.3 死锁
9.4 读写锁
9.5 条件变量
9.6 信号量
9.7 进程间锁
9.7.1 进程间pthread_mutex
9.7.2 文件锁
9.8 习题
10 网络基础
10.1 模型
10.1.1 OSI七层模型
10.1.2 TCP/IP四层模型
10.2 通信过程
10.3 协议格式
10.3.1 数据包封装
10.3.2 以太网帧格式
10.3.3 ARP数据报格式
10.3.4 IP段格式
10.3.5 UDP数据抱格式
10.3.6 TCP数据报格式
10.4 再议TCP
10.4.1 tcp状态转换图
10.4.2 TCP流量控制(滑动窗口)
10.4.3 TCP半链接状态
10.4.4 2MSL
10.5 名词术语解析
10.5.1 什么是路由(route)
10.5.2 路由器工作原理
10.5.3 路由表(Routing Table)
10.5.4 以太网交换机工作原理
10.5.5 hub工作原理
10.5.6 半双工/全双工
10.5.7 DNS服务器
10.5.8 局域网(local area network;LAN)
10.5.9 广域网(wide area network;WAN)
10.5.10 端口
10.5.11 MTU
10.6 常见网络知识面试题:
11 socket编程
11.1 预备知识
11.1.1 网络字节序
11.1.2 IP地址转换函数
11.1.3 sockaddr数据结构
11.2 网络套接字函数
11.2.1 socket
11.2.2 bind
11.2.3 listen
11.2.4 accept
11.2.5 connect
11.3 C/S模型-TCP
11.3.1 server
11.3.2 client
11.4 C/S模型-UDP
11.4.1 server
11.4.2 client
11.5 出错处理封装函数
11.5.1 wrap.c
11.5.2 wrap.h
11.6 练习
12 高并发服务器
12.1 多进程并发服务器
12.1.1 server
12.1.2 client
12.2 多线程并发服务器
12.2.1 server
12.2.2 client
12.3 多路I/O转接服务器
12.3.1 三种模型性能分析
12.3.2 select
12.3.3 poll
12.3.4 epoll
12.4 线程池并发服务器
12.5 UDP局域网服务器
12.6 其它常用函数
12.6.1 名字与地址转换
13 shell编程
14 正则表达式
15 错误处理机制
15.1 errno
15.2 perror
15.3 strerror
16 syslog机制
17 命令行参数
18 时间函数
18.1 文件访问时间
18.2 cpu使用时间
19 工具
19.1 网络工具
19.1.1 ifconfig
19.1.2 ping
19.1.3 netstat
19.1.4 设置IP
20 小项目实战
20.1 shell
20.2 多线程cp
20.3 哲学家就餐
20.4 数字多媒体广告机系统
20.5 高并发即时通信服务器
20.6 web服务器
21 大项目实战
21.1 研发中
Linux 系统编程 传智播客-邢文鹏1 2014-09-27 1http://blog.csdn.net/itcastcpp
前言 学习目标 成为linux/unix系统程序员 学习态度 * 谦虚 * 严谨 * 勤思 * 善问 学习方法 从本章开始学习各种Linux系统函数,这些函数的用法必须结合Linux内核的工作原理 来理解,因为系统函数正是内核提供给应用程序的接口,而要理解内核的工作原理,必 须熟练掌握C语言,因为内核也是用C语言写的,我们在描述内核工作原理时必然要用“指 针”、“结构体”、“链表”这些名词来组织语言,就像只有掌握了英语才能看懂英文书一 样,只有学好了C语言才能看懂我描述的内核工作原理。读者看到这里应该已经熟练掌握了C 语言了,所以应该有一个很好的起点了。我们在介绍C标准库时并不试图把所有库函数讲一 遍,而是通过介绍一部分常用函数让读者把握库函数的基本用法,在掌握了方法之后,书上 没讲的库函数读者应该自己查Man Page学会使用。同样,本书的第三部分也并不试图把所有 的系统函数讲一遍,而是通过介绍一部分系统函数让读者理解操作系统各部分的工作原理, 在有了这个基础之后就应该能够看懂Man Page学习其它系统函数的用法。 读者可以结合[APUE2e]学习本书的第三部分,该书在讲解系统函数方面更加全面,但 对于内核工作原理涉及得不够深入,而且假定读者具有一定的操作系统基础知识,所以并 不适合初学者。该书还有一点非常不适合初学者,作者不辞劳苦,在N多种UNIX系统上做了 实验,分析了它们的内核代码,把每个系统函数在各种UNIX系统上的不兼容特性总结得非 常详细,很多开发者需要编写可移植的应用程序,一定爱死他了,但初学者看了大段大段 的这种描述(某某函数在4.2BSD上怎么样,到4.4BSD又改成怎么样了,在SVR4上怎么样,到 Solaris又改成怎么样了,现在POSIX标准是怎么统一的,还有哪些系统没有完全遵守POSIX 标准)只会一头雾水,不看倒还明白,越看越不明白了。也正因为该书要兼顾各种UNIX系 统,所以没法深入讲解内核的工作原理,因为每种UNIX系统的内核都不一样。而本书的侧重 点则不同,只讲Linux平台的特性,只讲Linux内核的工作原理,涉及体系结构时只讲x86平 台,对于初学者来说,绑定到一个明确的平台上学习就不会觉得太抽象了。当然本书的代码 也会尽量兼顾可移植性,避免依赖于Linux平台特有的一些特性。 只听不练肯定学不会Linux,每个知识点都需要去动手实践
目录 前言 目录 1 文件I/O 1.1 C标准函数与系统函数的区别 . . . . . . . . . . . . . . . . . . . . . 1.1.1 I/O缓冲区 . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1.2 效率 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1.3 程序的跨平台性 . . . . . . . . . . . . . . . . . . . . . . . 1.2 PCB概念 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2.1 task_struct结构体 . . . . . . . . . . . . . . . . . . . . . . 1.2.2 files_struct结构体 . . . . . . . . . . . . . . . . . . . . . 1.3 open/close . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3.1 文件描述符 . . . . . . . . . . . . . . . . . . . . . . . . . 1.3.2 最大打开文件个数 . . . . . . . . . . . . . . . . . . . . . . 1.4 read/write . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.5 阻塞和非阻塞 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.5.1 阻塞读终端 . . . . . . . . . . . . . . . . . . . . . . . . . 1.5.2 非阻塞读终端 . . . . . . . . . . . . . . . . . . . . . . . . 1.5.3 非阻塞读终端和等待超时 . . . . . . . . . . . . . . . . . . . 1.6 lseek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.7 fcntl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.7.1 用fcntl改变File Status Flag . . . . . . . . . . . . . . . . . 1.8 ioctl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.9 习题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 文件系统 2.1 ext2文件系统 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 目录中记录项文件类型 . . . . . . . . . . . . . . . . . . . . 2.1.2 数据块寻址 . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 stat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 chmod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4 chown . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5 utime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.6 truncate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.7 link . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.7.1 link i iii 1 1 1 1 1 2 2 2 2 2 4 5 6 6 8 9 9 10 10 11 12 15 15 16 17 17 18 18 19 19 19 19
2.7.2 symlink . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.7.3 readlink 2.7.4 unlink . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.8 rename . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.9 chdir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.10 getcwd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.11 pathconf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.12 目录操作 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.12.1 mkdir . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.12.2 rmdir . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.12.3 opendir/fdopendir . . . . . . . . . . . . . . . . . . . . . . 2.12.4 readdir . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.12.5 rewinddir . . . . . . . . . . . . . . . . . . . . . . . . . . 2.12.6 telldir/seekdir . . . . . . . . . . . . . . . . . . . . . . . 2.12.7 closedir . . . . . . . . . . . . . . . . . . . . . . . . . . 2.12.8 递归遍历目录 . . . . . . . . . . . . . . . . . . . . . . . . 2.13 VFS虚拟文件系统 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.14 练习 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.13.1 dup/dup2 3 进程 3.1 进程环境 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 进程状态 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3 进程原语 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.1 fork . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.2 exec族 . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.3 wait/waitpid . . . . . . . . . . . . . . . . . . . . . . . . 3.4 练习 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 进程间通信 4.1 pipe管道 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2 fifo有名管道 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 内存共享映射 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.1 mmap/munmap . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.2 进程间共享通信 . . . . . . . . . . . . . . . . . . . . . . . 4.4 Unix Domain Socket . . . . . . . . . . . . . . . . . . . . . . . . . 4.5 习题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 信号 5.1 信号的概念 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1.1 信号编号 . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1.2 信号机制 . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1.3 信号产生种类 . . . . . . . . . . . . . . . . . . . . . . . . 5.1.4 信号产生原因 . . . . . . . . . . . . . . . . . . . . . . . . 5.2 进程处理信号行为 . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3 信号集处理函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 20 20 20 20 20 21 21 21 21 21 21 22 22 22 22 24 24 26 27 28 30 30 30 32 35 37 39 39 41 42 42 44 46 46 49 49 49 49 50 51 52 53
5.6.1 signal 5.4 PCB的信号集 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.1 sigprocmask . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.2 sigpending . . . . . . . . . . . . . . . . . . . . . . . . . 5.5 信号捕捉设定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.1 利用SIGUSR1和SIGUSR2实现父子进程同步输出 . . . . . . . . . . 5.6 C标准库信号处理函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.7 可重入函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.8 信号引起的竞态和异步I/O . . . . . . . . . . . . . . . . . . . . . . 5.8.1 时序竞态 . . . . . . . . . . . . . . . . . . . . . . . . . . 5.8.2 全局变量异步I/O . . . . . . . . . . . . . . . . . . . . . . . 5.8.3 可重入函数 . . . . . . . . . . . . . . . . . . . . . . . . . 5.8.4 避免异步I/O的类型 . . . . . . . . . . . . . . . . . . . . . . 5.9 SIGCHLD信号处理 . . . . . . . . . . . . . . . . . . . . . . . . . . 5.9.1 SIGCHLD的产生条件 . . . . . . . . . . . . . . . . . . . . . . 5.9.2 status处理方式 . . . . . . . . . . . . . . . . . . . . . . . 5.10 向信号捕捉函数传参 . . . . . . . . . . . . . . . . . . . . . . . . . 5.10.1 sigqueue . . . . . . . . . . . . . . . . . . . . . . . . . . 5.10.2 sigaction . . . . . . . . . . . . . . . . . . . . . . . . . . 5.11 信号中断系统调用 . . . . . . . . . . . . . . . . . . . . . . . . . . 5.12 练习 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 进程间关系 6.1 终端 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.1 网络终端 . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 进程组 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3 会话 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 守护进程 7.1 概念 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.2 模型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3 习题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 线程 8.1 线程概念 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.1 什么是线程 . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.2 线程和进程的关系 . . . . . . . . . . . . . . . . . . . . . . 8.1.3 线程间共享资源 . . . . . . . . . . . . . . . . . . . . . . . 8.1.4 线程间非共享资源 . . . . . . . . . . . . . . . . . . . . . . 8.1.5 线程优缺点 . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.6 pthread manpage . . . . . . . . . . . . . . . . . . . . . . . 8.2 线程原语 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2.1 pthread_create 8.2.2 pthread_self 8.2.3 pthread_exit 8.2.4 pthread_join 53 53 54 55 56 56 56 56 57 57 58 58 59 59 59 60 61 61 61 61 61 63 63 64 65 66 69 69 69 70 71 71 71 71 72 72 72 73 73 73 74 75 75
. . . . . . . . . . . . . . . . . . . . . . . 8.2.5 pthread_cancel 8.2.6 pthread_detach . . . . . . . . . . . . . . . . . . . . . . . 8.2.7 pthread_equal . . . . . . . . . . . . . . . . . . . . . . . . 8.3 线程终止方式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.4 线程属性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.4.1 线程属性初始化 . . . . . . . . . . . . . . . . . . . . . . . 8.4.2 线程的分离状态(detached state) . . . . . . . . . . . . . . 8.4.3 线程的栈地址(stack address) . . . . . . . . . . . . . . . . 8.4.4 线程的栈大小(stack size) . . . . . . . . . . . . . . . . . 8.4.5 线程属性控制实例 . . . . . . . . . . . . . . . . . . . . . . 8.5 NPTL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.6 细节注意 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.7 练习 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 线程同步 9.1 线程为什么要同步 . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2 互斥量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2.1 临界区(Critical Section) . . . . . . . . . . . . . . . . . 9.2.2 临界区的选定 . . . . . . . . . . . . . . . . . . . . . . . . 9.2.3 互斥量实例 . . . . . . . . . . . . . . . . . . . . . . . . . 9.3 死锁 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.4 读写锁 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.5 条件变量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.6 信号量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.7 进程间锁 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.7.1 进程间pthread_mutex . . . . . . . . . . . . . . . . . . . . . 9.7.2 文件锁 . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.8 习题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 77 78 78 79 79 79 80 81 81 82 83 83 85 86 86 86 87 87 88 88 89 90 92 92 93 94 10 网络基础 97 10.1 模型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 10.1.1 OSI七层模型 . . . . . . . . . . . . . . . . . . . . . . . . . 97 10.1.2 TCP/IP四层模型 . . . . . . . . . . . . . . . . . . . . . . . 98 10.2 通信过程 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 10.3 协议格式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 10.3.1 数据包封装 . . . . . . . . . . . . . . . . . . . . . . . . . 100 10.3.2 以太网帧格式 . . . . . . . . . . . . . . . . . . . . . . . . 100 10.3.3 ARP数据报格式 . . . . . . . . . . . . . . . . . . . . . . . . 101 10.3.4 IP段格式 . . . . . . . . . . . . . . . . . . . . . . . . . . 102 10.3.5 UDP数据抱格式 . . . . . . . . . . . . . . . . . . . . . . . . 103 10.3.6 TCP数据报格式 . . . . . . . . . . . . . . . . . . . . . . . . 105 10.4 再议TCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 10.4.1 tcp状态转换图 . . . . . . . . . . . . . . . . . . . . . . . . 106 10.4.2 TCP流量控制(滑动窗口) . . . . . . . . . . . . . . . . . . . . 109 10.4.3 TCP半链接状态 . . . . . . . . . . . . . . . . . . . . . . . . 110 10.4.4 2MSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
分享到:
收藏