基础
概念
linux基本概念
1
linux 系统编程,使用linux提供的api进行编程
2
linux只是内核,对应的发行版本,ubuntu , centos,debian
3
linux其实是类unix 系统
4
linux 的api大部分是c语言编写的
大纲
系统编程
系统调用io
文件系统
进程
进程间通信
多线程
线程同步与异步
网络编程
基本网络常识
socket相关api
多进程服务器模型
多线程服务器模型
io 复用服务器模型
高并发服务器框架
tinyHttp
libevent
nginx
linux文件
文件类型
普通文件:
文本文件
二进制文件
目录文件
设备文件
管道文件
套接字文件
符号链接文件
杂项
32位机修改文件扩展最大值
文件顶添加
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
设置可以 off_t 为long long int 类型,在32位机下产生大于2g的文件
系统api
文件以及文件夹的访问权限
int access(const char *pathname,int mode);
修改文件属性
int fcntl(int fd,int cmd);
int fcntl(int fd,int cmd,long arg);
cmd :
F_GETFL 获取文件描述符对应的文件标志,通过返回值返回,
F_SETFL 设置文件描述符对应的标志位,O_APPEND,O_ASYNC,O_DIRECT,O_NOATIME和O_NONBLOCK,通过第三个参数arg来传递标志
int fsync(int fd) 刷新缓冲区
文件系统格式
概览
windows 下的文件磁盘格式有FAT32,FAT16,NTFS 格式
linux : ext2 ,ext3,ext4 迭代关系,linuxswap,vfat等几种格式
ext2
磁盘信息存储区
在磁盘的开头, boot block 启动块,保存着分区表的信息 1k
分区类型
主分区
扩展分区
逻辑分区
每个分区可以格式化成不同的文件系统
读写的最小单位是一个扇区,一个扇区一般是512个字节
一个块一般是扇区的整数倍
一个分区:
一个分区先分组,每个组的开头都会有个super block ,
super block, 这个块是记录了几个扇区组成,mount 挂载的时间,以及文件的系统类型
分组的(块)组成
- super block
- GDT (group descriptor table) 记录的当前分组的使用情况,inode,资源等 ,同时也保存了其他分组的信息,备份其他组的信息
- blocks Bitmap 块位图,记录当前分组块的使用情况,
- inode Bitmap inode位图,记录inode的使用情况
- inode table inode表, 文件inode的存储信息情况(128字节),存储了文件权限,目录,文件大小,创建/修改/访问时间,用户信息,文件名,链接等文件属性,且文件属性在前64字节,其后(60)存储了数据块指针,指针0-指针11直接寻址,指针12到指针14,间接寻址,指针12 一级间接寻址,指针13二级间接寻址,指针14三级间接寻址,寻址在全局有效,并不局限当前分组
- data block 数据块
硬链接 并不会重新分配inode ,只是把硬链接计数增加
目录文件
大小是4096
空目录下,会有当前目录以及上级目录的记录项,保存在目录 文件的数据块
文件目录的数据块,存储了各文件的记录项;
记录项的数据有:
文件名字,文件的inode, 记录项长度,文件类型
每个记录项的长度都不一样
文件打开流程
例 : /home/log
根目录的inode 固定为 2
进入 / 根目录 在根目录下查找记录项,根据名字找到home 的inodeNumber
根据home 的inodeNumber 找到home 的记录项,根据名字找到log 的inodeNumber,
此时文件的inodeNumber 已经找到,可以根据inodeNumber 找到数据块指针,从而找到数据块
#### 文件的常规操作
沾住位
在文件夹中的作用:所有用户都可以在该文件夹中创建,删除, 且只能操作属于自己的或者有权限操作的文件
标识为原本执行权限位置的标识变更为t
例: drwxrwxrwx —> 粘住位之后变更为 drwxrwxrwt
t 标识即有执行权限x也有粘住位
T 标识即只有粘住位,没有执行权限x
使用:
chmod a+t file
SUID / SGID
S 标识表示只有s权限
s 表示有执行权限和s权限
s权限 : 让用户执行者权限提升到该文件的用户组与用户的权限
例 :
chmod u+s …..
chmod o-s ….
truncate 截断文件
int truncate(const char *pathm,off_t length);
int ftruncate(int fd, off_t length);
EACCESS #参数path所指定的文件无法存取。
EROFS #欲写入的文件存在于只读文件系统内
EFAULT #参数path指针超出可存取内存空间
EINVAL #参数path包含不合法字符
ENAMETOOLONG #参数path太长
ENOTDIR #参数path路径并非一目录
EISDIR #参数path 指向一目录
ETXTBUSY #参数path所指的文件为共享程序,而且正被执行中
link 创建硬链接
int link(const char*oldpath,const char *newPath);
symlink 建立文件链接符号
int symlink( const char * oldpath,const char * newpath);
符号链接没有文件系统限制
返回值:
成功则返回0,失败返回1,错误原因存于errno。
EPERM #参数oldpath与newpath所指的文件系统不支持符号连接
EROFS #欲测试写入权限的文件存在于只读文件系统内
EFAULT #参数oldpath或newpath指针超出可存取内存空间。
ENAMETOOLONG #参数oldpath或newpath太长
ENOMEM #核心内存不足
EEXIST #参数newpath所指的文件名已存在。
EMLINK #参数oldpath所指的文件已达到最大连接数目
ELOOP #参数pathname有过多符号连接问题
ENOSPC #文件系统的剩余空间不足
EIO I/O #存取错误
readlink 取得符号链接所指文件路径字符串
int readlink(const path,char *buf,size_t buf);
函数说明: readlink()会将参数path的符号连接内容存到参数buf所指的内存空间,返回的内容不是以NUL
符串结尾,但会将字符串的字符数返回。若参数bufsiz小于符号连接的内容长度,过长的内容会被截断。
返回值:
执行成功则传符号连接所指的文件路径字符串,失败则返回1,错误代码存于errno。
EACCESS #取文件时被拒绝,权限不够
EINVAL #参数bufsiz 为负数
EIO I/O #存取错误。
ELOOP #欲打开的文件有过多符号连接问题。
ENAMETOOLONG #参数path的路径名称太长
ENOENT #参数path所指定的文件不存在
ENOMEM #核心内存不足
ENOTDIR #参数path路径中的目录存在但却非真正的目录。
unlink 删除文件
int unlink(const char * pathname);
如果是符号链接,删除符号链接,
如果是硬链接,硬链接数减1,当减为0时,释放数据块和inode
如果文件硬连接数为0,但有进程已打开该文件,则在该程序结束之后会自动删除该文件
返回值 :成功则返回0,失败返回1,错误原因存于errno
EROFS #文件存在于只读文件系统内
EFAULT #参数pathname指针超出可存取内存空间
ENAMETOOLONG #参数pathname太长
ENOMEM #核心内存不足
ELOOP #参数pathname 有过多符号连接问题
EIO I/O #存取错误
rename 更改文件名字或位置
int rename(const char * oldpath,const char *newpath);
函数说明: rename()会将参数oldpath 所指定的文件名称改为参数newpath所指的文件名称。若newpath所指定的文
件已存在,则会被删除。
返回值:执行成功则返回0,失败返回1,错误原因存于errno
getcwd 获取当前工作目录
char *getcwd(char *buf, size_t size);
cwd current work directory
在哪里运行的就是哪个目录
chdir 改变当前的工作目录
int chdir(const char* path);
int fchdir(int fd);
函数说明: chidr、fchdir用来将当前的工作目录改变成以参数path指定的路径、或者fd 所指的文件描述词。
返回值: 执行成功则返回0,失败返回1,errno为错误代码
vfs 虚拟文件系统 virtual file system
统一各个文件系统的差异,使得在不同的文件系统就可以使用一样的接口
dup
int dup(int oldfd); 复制一个文件描述符指向old 资源
int dup2(int oldfd,int newfd); 复制一个文件描述符到指定的新的文件描述符,如果新的描述符已经被使用,将会关闭该描述符再进行复制
文件属性
stat
struct stat 该结构体用来描述linux系统文件中的文件属性的结构
int stat(const char *path,struct stat * struct_stat);
该函数返回链接文件的内容
int lstat(const char *path ,struct stat*struct_stat);
int fstat(int fdp,struct stat *struct_stat);
struct stat {
mode_t st_mode; //文件对应的模式,文件,目录等
ino_t st_ino; //inode节点号
dev_t st_dev; //设备号码
dev_t st_rdev; //特殊设备号码
nlink_t st_nlink; //文件的硬链接数连接数
uid_t st_uid; //文件所有者
gid_t st_gid; //文件所有者对应的组
off_t st_size; //普通文件,对应的文件字节数
time_t st_atime; //文件最后被访问的时间
time_t st_mtime; //文件内容最后被修改的时间
time_t st_ctime; //文件属性inode改变时间
blksize_t st_blksize; //文件内容对应的块大小
blkcnt_t st_blocks; //文件内容对应的块数量
};
S_IFMT 0170000 文件类型的位遮罩
S_IFLNK 0120000 符号连接
S_IFREG 0100000 一般文件
S_IFBLK 0060000 区块装置
S_IFDIR 0040000 目录
S_IFCHR 0020000 字符装置
S_IFIFO 0010000 先进先出
S_ISUID 04000 文件的(set user‐id on execution)位
S_ISGID 02000 文件的(set group‐id on execution)位
S_ISVTX 01000 文件的sticky位
S_IRUSR 00400 文件所有者具可读取权限
S_IWUSR 00200 文件所有者具可写入权限
S_IXUSR 00100 文件所有者具可执行权限
S_IRGRP 00040 用户组具可读取权限
S_IWGRP 00020 用户组具可写入权限
S_IXGRP 00010 用户组具可执行权限
S_IROTH 00004 其他用户具可读取权限
S_IWOTH 00002 其他用户具可写入权限
S_IXOTH 00001 其他用户具可执行权限
stat 宏
例如:
S_ISLNK (st_mode) 判断是否为符号连接
S_ISREG (st_mode) 是否为一般文件
S_ISDIR (st_mode) 是否为目录
S_ISCHR (st_mode) 是否为字符设备文件
S_ISSOCK (st_mode) 是否为socket
ctime
将时间转换成字符串
char *ctime(const time_t*time);
chmod
更改文件权限
int chmoe(const char *path,mode_t mode);
int fchmod(int fd,mode_t mode);
参数 mode 有下列数种组合:
1、S_ISUID 04000 文件的 (set user‐id on execution)位
2、S_ISGID 02000 文件的 (set group‐id on execution)位
3、S_ISVTX 01000 文件的sticky 位
4、S_IRUSR 00400 文件所有者具可读取权限
5、S_IWUSR 00200 文件所有者具可写入权限
6、S_IXUSR 00100 文件所有者具可执行权限
7、S_IRGRP 00040 用户组具可读取权限
8、S_IWGRP 00020 用户组具可写入权限
9、S_IXGRP 00010 用户组具可执行权限
10、S_IROTH 00004 其他用户具可读取权限
11、S_IWOTH 00002 其他用户具可写入权限
12、S_IXOTH 00001 其他用户具可执行权限
chown
更改所属用户
int chown(const char *path, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int lchown(const char *path, uid_t owner, gid_t group);
/*lchown是改变符号链接本身的所有者,而不是该符号链接所指向的文件。*/
utime
修改文件的访问修改时间
int utime(const char *filename,struct utimbuf *buf);
struct utimbuf{
time_t actime;
time_t modtime;
}
如果参数buf为空指针(NULL),则该文件的存取时间和更改时间全部会设为目前时间。执行成功则返回0,失败
返回1,错误代码存于errno。错误代码 EACCESS 存取文件时被拒绝,权限不足ENOENT 指定的文件不存在。
mkdir
int mkdir(const char *pathname, mode_t mode);
rmdir
int rmdir(const char *pathname);
opendir 打开文件夹
DIR *opendir(const char *name);
DIR *fdopendir(int fd);
函数说明: opendir()用来打开参数name指定的目录,并返回DIR*形态的目录流,和open()类似,接下来对目录的
读取和搜索都要使用此返回值。
返回值: 成功则返回DIR* 型态的目录流,打开失败则返回NULL。
EACCESS #权限不足
EMFILE #已达到进程可同时打开的文件数上限。
ENFILE #已达到系统可同时打开的文件数上限。
ENOTDIR #参数name非真正的目录
ENOENT #参数name 指定的目录不存在,或是参数name 为一空字符串。
ENOMEM #核心内存不足。
readdir
struct dirent *readdir(DIR *dirp);
struct dirent {
ino_t d_ino; /* 此目录进入点的inode */
off_t d_off; /* 目录文件开头至此目录进入点的位移 */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* 所指的文件类型*/
char d_name[256]; /* 文件名 */
};
函数说明: readdir()返回参数dir目录流的下个目录进入点。
返回值: 成功则返回下个目录进入点。有错误发生或读取到目录文件尾则返回NULL。EBADF参数dir为无效的目录
流。
DT_BLK #This is a block device.
DT_CHR #This is a character device.
DT_DIR #This is a directory.
DT_FIFO #This is a named pipe (FIFO).
DT_LNK #This is a symbolic link.
DT_REG #This is a regular file.
DT_SOCK #This is a UNIX domain socket.
DT_UNKNOWN #The file type could not be determined
rewinddir 重置读取目录的位置
void rewinddir(DIR *dirp);
设置流为原来读取位置
relldir,seekdir
long telldir(DIR *dirp);
void seekdir(DIR *dirp, long offset);
函数说明: seekdir()用来设置参数dir目录流目前的读取位置,在调用readdir()时便从此新位置开始读取。参数
offset 代表距离目录文件开头的偏移量。
telldir()返回参数dir目录流目前的读取位置。此返回值代表距离目录文件开头的偏移量返回值返回下个
读取位置,有错误发生时返回1。
closedir 关闭目录
int closedir(DIR *dirp);