首页 > 其他分享 >20201306吴龙灿第七、八章学习笔记

20201306吴龙灿第七、八章学习笔记

时间:2022-09-25 17:25:25浏览次数:59  
标签:文件 八章 int pid char 吴龙灿 进程 include 20201306

知识点归纳

一、文件操作

1.文件操作级别

​ 文件操作分为五个级别,按照从低到高的顺序可以如下表示:

硬盘级别

​ 这些操作多是针对系统的实用程序,一般用户不会涉及到它们的运用,但是这些操作是创建和维护系统的关键。这些操作包括:

1.fdisk: 将硬盘、U盘或者SDC盘分区
2.mkfs: 格式化磁盘分区,为系统做好准备
3.fsck: 检查和维修系统
4.碎片整理: 压缩系统中的文件

操作系统内核中的文件系统函数
​ 每个操作系统内核都是可以为基本文件操作提供支持的。它们有一个共同点,就是有 k 前缀:

系统调用

​ 用户模式用来访问内核函数的工具,在C语言中是一系列文件操作相关的库函数,如
open() => kopen()
read() => kread()
lseek()...
close()...
这些函数在第十章中有较为详实的使用解析。
内核函数传输数据是按数据块的格式进行的。
​ 这些库函数会发出一个系统调用,使进程进入内核模式来执行相关的内核函数,以达到文件操作的目的。进程结束执行内核函数后就会回到用户模式。在内核模式下,每次读取的内容一般为 n KB的数据块,根据系统不同, n 的值会在1~8间变化 ,比如,在Linux中,硬盘默认的数据块大小为4KB,软盘为1KB。

I/O库函数

​ I/O库函数可以提供数据缓冲区,方便对数据按字符、行或者数据结构的形式进行读写,C语言中有许多常用的I/O库函数,比如 scanf() 等
​ 一些基本格式:
文件模式: fopen() , fread() ; fwrite() ,fseek() ,fclose() ,fflush()
字符模式: getc() ,getchar() , ugetc() ,putc() ,putchar()
行模式: gets() ,fgets() ,puts() ,fputs()
数据结构模式: scanf() ,fscanf() ,sscanf() ,printf() ,fprintf() ,sprintf()
除了读/写内存位置的函数 sscanf()和sprintf()以外,其他的所有I/O库函数都是建立在系统调用之上的。

用户命令

​ 在Linux系统中,会经常用到一些用户命令,如 mkdir ,ls ,mv ,cp等,除此自外还有如下用户命令
rmdir ,cd ,pwd ,link ,unlink ,rm ,cat ,chmod...
其中除了cd命令以外,其余都为一个可执行程序,这些程序通常会通过调用I/O库函数实现功能。

sh脚本

使用sh编程语言编写的一种脚本程序,虽然比系统调用方便,但是要手动输入命令写脚本,还要指定设备来进行输入。

2.文件I/O操作

下图为文件I/O操作示意图。

3.低级别文件操作

1.分区

​ 像给一块大容量硬盘分区,可以通过分区操作来将一个大存储空间分为不同的逻辑单元,各个分区可以格式化成为特定的文件文件系统,可以有效的隔离不同数据。
​ 在Linux系统下,可以通过如下操作创建一个虚拟磁盘映象文件:
dd if=/dev/zero of=disk20191314 bs=1024 count=1440

2.格式化分区​

fdisk 将一个存储设备划分为多个分区,但是刚刚划分出来的分区还需要经过格式化才可以存储文件,可以使用mkfs命令在特定的分区上建立 linux 文件系统,mkfs的一般格式如下:
mkfs [-V] [-t fstype] [fs-options] filesys [blocks]

3.挂载分区​

losetup 命令用于设置循环设备。循环设备可把文件虚拟成区块设备,籍以模拟整个文件系统,让用户得以将其视为硬盘驱动器,光驱或软驱等设备,并挂入当作目录来使用。​ losetup命令语法如下:
losetup [-d][-e <加密方式>][-o <平移数目>][循环设备代号][文件]

4.EXT2文件系统简介

ext2是Linux系统所默认的文件系统
它有如下的磁盘块:
BLOCK#0: 引导块 用于容纳从磁盘引导操作系统的引导程序,不会被文件操作系统使用
BLOCK#1: 超级块 在硬盘分区中字节偏移量为1024,超级块容纳了关于整个文件系统的信息
超级块有一些重要字段,这些字段表明了超级块的各段含义:
BLOCK#2: 块组表述符块 ext2将磁盘块分成若干组,每组8192块(约32K),每组都有一个块组描述符结构体
BLOCK#8: 块位图 表示某种项的位序列
BLOCK#9: 索引节点位图 代表一个文件的数据结构
BLOCK#10: 索引节点 大小为128字节的索引结构体,表示一个文件

二、使用系统调用进行文件操作

常用的系统调用
stat 获取文件状态信息
int stat(char *filename ,struct stat *buf)
int fstat(char filedes ,struct stat *buf)
int lstat(char *filename ,struct stat *buf)
open:打开一个文件进行读、写、追加
int open(char *file, int flags,int mode)
close:关闭打开的文件描述符
int close(int fd)
read:读取打开的文件描述符
int read(int fd, char buf[ 1, int count)
write:写入打开的文件描述符
int write(int fd, char buf[ ], int count)
lseek:重新定位文件描述符的读/写偏移量
int 1seek(int fd, int offset, int whence)
dup:将文件描述符复制到可用的最小描述符编号中
int dup(int oldfd);
dup2:将oldfd复制到newfd中,如果newfd已打开,先将其关闭
int dup2(int oldfd, int newfd)
link:将新文件硬链接到旧文件
int link(char *oldPath, char *newPath)
unlink:取消某个文件的链接;如果文件链接数为0,则删除文件
int unlink(char *pathname);
symlink:创建一个符号链接
int symlink(char *target, char *newpath)
readlink:读取符号链接文件的内容
int readlink(char *path, char *buf, int bufsize)
umask:设置文件创建掩码;文件权限为(mask&~umask)
int umask(int umask)

进程控制

1)getpid,getppid——获取进程识别号

include <sys/types.h>

include <unistd.h>

pid_t getpid(void);
获取进程标识号。这可以作为一个独一无二的临时文件名。
pid_t getppid(void);
获取父进程标示号。

2)fork——创建一个子进程

include <sys/types.h>

include <unistd.h>

pid_t fork(void);
通过完全复制当前进程创建一个新进程。
如果创建子进程成功,在父进程中返回子进程的进程标示符,在子进程中返回0。
如果失败,在父进程中返回-1,子进程不会被创建,errno被设置。
因为在fork()的调用处,整个父进程空间会原模原样地复制到子进程中,包括指令,
变量值,程序调用栈,环境变量,缓冲区,等等。所以,子进程和父进程是不能通过
程序内的变量(即使是全局变量)通信的,对于这两个进程来说,它们有各自的进程空间,
互不影响。但父进程和子进程可以通过管道,共享内存,等方式实现通信。

3)sleep——使进程睡眠指定的秒数

include <unistd.h>

unsigned int sleep(unsigned int seconds);
到达指定时间后返回0,若有信号中断,则返回剩余的秒数。

4)wait,waitpid——等待子进程终止

include <sys/types.h>

include <sys/wait.h>

pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
等待子进程的状态发生变化,并且获得状态变化的信息。状态变化是指:子进程终止;子进程被信号停止;
或者子进程被信号恢复。
等待子进程终止可以让系统释放子进程的资源,如果不等待,那么就会产生僵尸进程。
如果一个子进程状态发生变化,系统调用立即返回,否则就一直阻塞,直到子进程状态发生变化,或者一个
信号中断系统调用。
wait(&status);等价于waitpid(-1, &status, 0);
wait等待一个子进程终止,waitpid等待pid指定的子进程状态改变。默认waitpid仅等待子进程终止,可以
通过options来改变行为。
wait执行成功返回终止子进程的进程号,否则返回-1.
waitpid执行成功返回状态改变子进程的进程号;如果指定了WHOHANG并且pid指定的子进程存在,但是
状态没有改变,立即返回0。错误返回-1.
子进程的返回状态由status存储,可以通过宏来获得信息。如果不关心,可以将status设成NULL。

5)execve——执行程序

include <unistd.h>

int execve(const char *filename, char *const argv[],
char *const envp[]);

最有收获的地方

因为平时我所应用的操作系统就是Windows系列,所以我并没有体会到操作系统的原理。Windows几乎将所有的进程都通过窗口这个东西封装起来了,所以即使Windows很人性化,提高了使用性,但是却很难真正搞懂这其中的原理所在。
这两章都是针对于系统调用层面的文件操作,因为之前使用Linux系统输入过很多命令行,但都不懂这个作用,但是再教材上学到了有关这些命令行的程序,收获巨大。我最感兴趣的是ls程序。
ls 如此重要的原因在于它允许查看目录中的文件。将经常使用它来列出目录内容。 ls 不是一个复杂的命令,实现起来也很容易,但它确实包含许多不同的选项,可用于列出包含附加信息的文件。
在这过程中,你可能会发现其中一些选项非常有用,即使 ls 本身总是足以列出内容。掌握 ls 命令将使你更有效地列出目录内容和查找文件。它也可以在 Bash 脚本中使用,以帮助其他工具操作文件。

问题

怎么实现ls命令?

解决思路

我们已经通过在命令行上输入ls命令,列出目录中包含的文件和子目录。

-a 选项还将列出隐藏文件(名称以 . 开头的文件)。 除非您在根目录中,否则它还会列出 . (当前工作目录)和 … (向上一个目录)作为文件。
那么我们如何读取目录、文件信息呢?
最多常见的readdir使用方式:

include<stdio.h>

include<dirent.h>

include<string.h>

include <stdio.h>

include

include <stdlib.h>

using namespace std;

define FILE_NAME "/opt/code/linux_command_code"

int main(int argc, char **argv)
{
DIR *dir;
struct dirent *ptr;
dir = opendir(FILE_NAME);
if(NULL == dir)
{
cout << "opendir is NULL" << endl;
return -1;
}
while( (ptr = readdir(dir))!=NULL)
{
printf("d_ino:%ld d_off:%ld d_name: %s\n", ptr->d_ino,ptr->d_off,ptr->d_name);
}
closedir(dir);

return 0;

}
编译运行:

实践内容与截图,代码链接

实践内容我选择再分区范围内进行:
再Linux下,创建一个名为mydisk的虚拟磁盘映像文件。
dd if=/dev/zero of=mydisk bs=1024 count=1440
然后在磁盘上运行fdisk:
截图如下:

标签:文件,八章,int,pid,char,吴龙灿,进程,include,20201306
From: https://www.cnblogs.com/wulongcan20201306/p/16728247.html

相关文章

  • 《Unix/Linux系统编程》第七、八章学习笔记 20201209戴骏
    一、知识点归纳第七章文件操作1.文件操作级别文件操作分为五个级别,按照从低到高的顺序排列如下.(1)硬件级别:硬件级别的文件操作包括:fdisk:将硬盘、U盘或SDC盘分区。......
  • 20201220蔡笃俊《信息安全系统设计与实现》第七、八章学习笔记
    一、任务内容自学教材第7,8章,提交学习笔记(10分)知识点归纳以及自己最有收获的内容(3分)问题与解决思路(2分)实践内容与截图,代码链接(3分)...(知识的结构化,知识的完整性等,提......
  • 第十八章 装饰器
    一、装饰器介绍1.为何要用装饰器软件的设计应该遵循开放封闭原则,即对扩展是开放的,而对修改是封闭的。对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应......
  • 第八章读数笔记
    第八章读书笔记8.1系统调用在操作系统中,进程以两种不同的模式运行,即内核模式和用户模式,简称Kmode和Umode。在Umode中,进程的权限非常有限。它不能执行任何需要特殊权限的......
  • CSAPP(第三版)第八章异常控制流学习笔记
    定义:从给处理器加点开始,知道你断电为止,程序计数器假设一个值的序列\(a_0,a_1,...,a_{n-1}\)其中,每个\(a_k\)是某个响应的指令\(I_k\)的地址。每次从\(a_k\)到\(a_{k+1}\)......
  • 第八章 filebeat收集日志与kibana画图
    一、filebeat收集单日志到本地文件1.配置#编辑Filebeat配置文件[root@web01~]#vim/etc/filebeat/filebeat.ymlfilebeat.inputs:-type:logenabled:truepat......
  • 第八章 数组的使用和信号控制
    一、数组介绍1.什么是数组? 数组就是一系列元素的集合,一个数组内可以存放多个元素 2.为何要用数组? 我们可以用数组将多个元素汇总到一起,避免单独定义的麻烦二、数......
  • 第十八章 Ansible-playbook-Role基础介绍
    一、AnsibleRoles概述roles不管是Ansible还是saltstack,我在写一键部署的时候,都不可能把所有的步骤全部写入到一个'剧本'文件当中,我们肯定需要把不同的工作模块,拆分开来,解......
  • 第八章 Ansible-playbook基础介绍
    一、playbook简介PlayBook即"剧本","兵书"之意,PlayBook是由以下部分组成的:play(host):定义的是主机的角色。(主角还是配角)Book(task):定义的是具体执行的任务。(角色的......
  • 第八章 Redis数据持久化之AOF
    一、AOF概述AOF(Append-OnlyFile)记录Redis中每次的写命令,类似mysql中的binlog,服务重启时会重新执行AOF中的命令将数据恢复到内存中,RDB(按策略持久化)持久化方式记录的粒......