day07

来源:互联网 发布:男士护肤 知乎 旁氏 编辑:程序博客网 时间:2024/05/29 03:12
回忆昨天内容:
一、文件的操作lseek
二、使用mmap将文件映射到进程的虚拟地址空间。
三、获取文件的元数据
今天的内容:
一、文件夹的操作
系统提供了以下库函数,来操作文件夹
opendir(3)
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:打开一个文件夹
参数:
name:指定了要打开的文件夹的名字
返回值:
NULL   错误   errno被设置
返回一个具体的地址

closedir(3)
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
功能:关闭一个文件夹
参数:
dirp:指定了要关闭的文件夹(opendir(3)的返回值)
返回值:
0   成功
-1   失败   errno被设置

readdir(3)
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
功能:读取文件夹的内容
参数:
dirp:指定文件夹。opendir(3)的返回值
struct dirent{
    ino_t  d_ino; /* inode number */
        off_t  d_off;       /* offset to the next dirent */
        unsigned short d_reclen;    /* length of this record */
        unsigned char  d_type;      /* type of file; not supported
                       by all file system types */
    char           d_name[256]; /* filename */
};



返回值:
NULL   到达文件夹的末尾或者错误产生
如果errno被设置了,代表了错误产生
成功调用返回一个地址。




举例验证 文件夹的操作。
代码参见diros.c

补充:
文件夹的内容包含什么?
文件夹里的所有文件。

drwxrwxr-x  9 tarena tarena 4096  3月 23 08:59 uc

uc$ls
day01         day03         day05         day07
day01.tar.gz  day03.tar.gz  day05.tar.gz
day02         day04         day06
day02.tar.gz  day04.tar.gz  day06.tar.gz
uc$pwd
/home/tarena/CSD1702/uc

r   读      w  写     x    通过

day07$ls -l
总用量 4
drwxrwxr-x 2 tarena tarena 4096  3月 23 09:19 test
day07$chmod a-x test
day07$ls -l
总用量 4
drw-rw-r-- 2 tarena tarena 4096  3月 23 09:19 test
-rw-rw-r-- 1 tarena tarena    0  3月 23 08:59 笔记
day07$cd test
bash: cd: test: 权限不够

二、文件重定向的实现原理
补充文件重定向的操作
文件重定位就是重新定位文件的流向。
要完成文件重定位的功能,需要将文件描述符的拷贝。

dup(2)
#include <unistd.h>
int dup(int oldfd);
功能:复制一个文件描述符
参数:
oldfd:拷贝的样本
返回值:
-1  失败   errno被设置
新的文件描述符

dup2(2)
int dup2(int oldfd, int newfd);
功能:复制一个文件描述符
参数:
oldfd:拷贝的样本
newfd:指定新的文件描述符
返回值:
-1  失败   errno被设置
新的文件描述符

举例实现文件重定向的功能。direct.c

三、文件锁
文件锁分为两种类型
强制锁、建议锁

根据锁的互斥性又可以分为
读锁(共享锁)    写锁(互斥锁)
如何实现文件锁?
使用fcntl(2)完成文件锁的功能。
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
功能:操作文件描述符
参数:
fd:指定要操作的文件描述符
cmd:对文件描述符的操作命令
F_GETLK 获取文件上的锁
F_SETLK  设置锁到文件。出现互斥锁的时候,非阻塞。
F_SETLKW 设置锁到文件,出现互斥锁的时候,阻塞。

struct flock {
       short l_type;    /* Type of lock: F_RDLCK,
                                   F_WRLCK, F_UNLCK */
       short l_whence;  /* How to interpret l_start:
                        SEEK_SET, SEEK_CUR, SEEK_END */
       off_t l_start;   /* Starting offset for lock */
       off_t l_len;     /* Number of bytes to lock */
       pid_t l_pid;     /* PID of process blocking our lock
                                   (F_GETLK only) */
};
返回值:
0   成功
-1 错误 errno被设置

编写代码验证文件锁的使用。
代码参见processA.c  processB.c

四、库函数和系统调用函数之间的关系(文件的操作)
库函数: fopen、fclose、fputc、fgetc  缓冲文件
系统调用  open、close、write、read   非缓冲文件

举例说明  代码参见file.c
typedef struct _IO_FILE FILE;

fopen(3)
分配结构体FILE的一块内存,在FILE类型中有一个成员变量_fileno,用于保存文件描述符。另外分配一块缓存,后边库函数对文件的读写操作是针对这块缓存的;调用open(2)打开相应的文件。

fgetc(3)
调用fgetc的时候,主要是针对缓存,从缓存中获取数据,如果缓存有数据,立即返回获取到的数据。如果缓存中没有数据,调用read(2),文件描述符有FILE类型的参数的_fileno传入。从系统中获取数据到缓存,然后fgetc(3)返回获取到的数据。

fputc(3)
调用fputc的时候,如果写缓存有空间,直接将字符写入到缓存;如果写缓存已经满,调用write(2)将写缓存中的内容写到文件,清楚缓存,然后将字符写入到写缓存。

fclose(3)
先清除缓存中的内容到文件,然后调用close(2)关闭文件描述符,然后,释放fopen(3)开辟的缓存空间。
五、杂项
chdir(2)
#include <unistd.h>
int chdir(const char *path);

getcwd(3)
#include <unistd.h>
char *getcwd(char *buf, size_t size);

link(2)
#include <unistd.h>
int link(const char *oldpath, const char *newpath);

unlink(2)
symlink(2)
rename(2)

chmod(2)
#include <sys/stat.h>
int  chmod(const char *path,mode_t mode);

六、进程基础
程序和进程的区别
程序是静态的,存放在磁盘上,是指令的集合。
进程是程序运行的实例。一个程序运行一次产生一个进程。

每个进程都有自己的pid,每个进程都有自己的PCB。
进程是资源分配的基本单位。

在linux操作系统下,进程之间的关系是父子关系或者兄弟关系。
所有的用户级进程形成了一颗树。
如何查看这颗树?
pstree

init是这颗树的树根,也是1号进程。是用户进程的第一个进程。

bash下自定义变量和环境变量的区别。
如何创建一个新的进程?
使用系统调用fork(2)创建新进程。
#include <unistd.h>
pid_t fork(void);
功能:创建一个子进程
参数:
void
返回值:
-1错误,在父进程里返回,子进程不被创建。errno被设置。
成功:
在父进程里返回子进程的pid。
在子进程中0被返回。

举例说明  子进程的创建
代码参见fork.c

总结:
一、文件夹的操作
二、文件重定向
三、文件锁的使用
四、库函数和系统调用函数之间的关系
五、文件操作的杂项
六、进程的基础
作业:
myls  filename
如果filename是文件夹,将文件夹里的内容长格式显示出来。
ls -l directory