Home Article Practice 02_系统调用

02_系统调用

2024-04-24 08:37  views:324  source:拼搏百天我要上蓝翔    

知识点1【系统调用】1、系统调用的概述系统调用: 就是内核 提供给用户可以操作内核 一组函数接口。用户 借助
系统调用 操作内核。进程的空间分为:内核空间 和 用户空间2、系统调用和库函数有啥区别系统调用 是内核提供的一
组函数接口。 内核提供库函数 是第三方的函数接口。 用户提供如果库函数没有调用 系统调用 该库函数不能操作 内
核 比如:字符串操作函数strcpy,bzero如果库函数 调用 系统调用 该库函数 能操作 内核 比如:fo
pen fclose fwrite fgets系统调用是需要时间的,程序中频繁的使用系统调用会降低程序的运行效
率。当运行内核代码时,CPU工作在内核态,在系统调用发生前需要保存用户态的栈和内存环境,然后转入内核态工作。系
统调用结束后,又要切换回用户态。这种环境的切换会消耗掉许多时间。3、C库中IO函数工作流程知识点2【文件描述符
】(重要)Linux将系统调用 打开或新建的文件 用非负整数 来表示。而这个非负整数 就是文件描述符。系统会为
每一个进程 分配文件描述符表,管理该进程的所有文件描述符。系统会为 每一个进程 打开三个文件描述符:0,1,2
0:标准输入设备(键盘) scanf1:标准输出设备(终端)printf2:标准错误输出 (终端)perror
1、文件描述符表是如何管理文件描述符的呢?文件描述符表 是通过 “位图” 来管理文件描述符。使用1024位二进
制位管理,位数代表的就是文件描述符,位上的值1表示打开,值0表示关闭。2、查看当前系统文件描述符最大数量查看:
ulimit -a修改:ulimit -n 20483、文件描述的案例知识点3【文件IO的操作】文件常用操作I
O:open close read write1、打开文件 open1 #include <sys/types
。h>2 #include <sys/stat。h>3 #include <fcntl。h>4 //两个参数的
open用于 打开已存在的文件5 int open(const char *pathname, int fla
gs);6 //三个参数的open用于 打开不存在的文件 mode就是文件在磁盘上的权限7 int open(
const char *pathname, int flags, mode_t mode);功能:打开文件,如
果文件不存在则可以选择创建。参数:pathname:文件的路径及文件名flags:打开文件的行为标志,必选项
O_RDONLY, O_WRONLY, O_RDWRmode:这个参数,只有在文件不存在时有效,指新建文件时指
定文件的磁盘权限返回值:成功:成功返回打开的文件描述符失败:-11、flags 文件的操作权限(read wr
ite)取值 含义O_RDONLY 以只读的方式打开O_WRONLY 以只写的方式打开O_RDWR 以可读、可
写的方式打开可选项,和必选项按位或起来取值 含义O_CREAT 文件不存在则创建文件,使用此选项时需使用mod
e说明文件的权限O_EXCL 如果同时指定了O_CREAT,且文件已经存在,则出错O_TRUNC 如果文件存在
,则清空文件内容O_APPEND 写文件时,数据添加到文件末尾O_NONBLOCK 对于设备文件, 以O_NO
NBLOCK方式打开可以做非阻塞I/O2、mode文件在磁盘的用户权限磁盘文件的用户权限分类:所有拥有者权限(
u)、同组用户权限(g)、其他用户权限(o)任何权限都分为:读(4)、写(2)、执行(1) 这3个数值可以组合
7--->可读可写可执行 6--->可读可写 5--->可读可执行 4--->只读3--->可写可执行 2--
->只写 1--->可执行mode的权限表示0xxx 每一个x都是(4,2,1)的组合0777 所有者、同组用
户、其他用户都是可读可写可执行0666 所有者、同组用户、其他用户都是可读可写0651 所有者可读可写 、同组
用户可读可执行、其他用户可执行3、mode的系统掩码查看掩码:umask文件的最终权限=给定的权限 & ~um
askumask mode:设置掩码,mode为八进制数umask -S:查看各组用户的默认操作权限2、clo
se关闭文件描述符1 #include <unistd。h>2 int close(int fd);功能:关闭
已打开的文件参数:fd : 文件描述符,open()的返回值返回值:成功:0失败: -1, 并设置errno注
意:close工作步骤,先将文件描述符的数量-1,当文件描述符的数量变为0的时候 ,系统回收文件描述符所占的内
核空间。3、向文件写数据write1 #include <unistd。h>2 ssize_t write(i
nt fd, const void *buf, size_t count);功能:把指定数目的数据写到文件(f
d)参数:fd : 文件描述符buf : 数据首地址count : 写入数据的长度(字节)返回值:成功:实际写
入数据的字节个数失败: - 1案例1:写入数据1 #include <stdio。h>2 #include <
unistd。h>3 #include <string。h>4 #include <sys/types。h>5
#include <sys/stat。h>6 #include <fcntl。h>7 int main(in
t argc, char const *argv[])8 {9 int fd = open("b。txt",
O_WRONLY | O_CREAT, 0666);10 if (fd < 0)11 {12 perror("
open");13 return 0;14 }15 printf("fd = %d\n", fd);1617
//写入文件数据18 char buf[128] = "";19 fgets(buf, sizeof(buf)
, stdin);20 buf[strlen(buf) ‐ 1] = 0;2122 write(fd, buf
, strlen(buf));2324 //关闭文件25 close(fd);26 return 0;27 }
4、read读取文件数据1 #include <unistd。h>2 ssize_t read(int fd,
void *buf, size_t count);功能:把指定数目的数据读到内存(缓冲区)参数:fd : 文
件描述符buf : 内存首地址count : 读取的字节个数返回值:成功:实际读取到的字节个数读完文件数据返回
0失败: - 11 #include <stdio。h>2 #include <unistd。h>3 #inc
lude <string。h>4 #include <sys/types。h>5 #include <sys/
stat。h>6 #include <fcntl。h>7 int main(int argc, char co
nst *argv[])8 {9 int fd = open("b。txt", O_RDONLY);10 if
(fd < 0)11 {12 perror("open");13 return 0;14 }15 print
f("fd = %d\n", fd);1617 //读取文件数据18 char buf[128] = "";1
9 int len = read(fd, buf, sizeof(buf));20 printf("读取的内容
%s, 长度:%d\n", buf, len);2122 //关闭文件23 close(fd);24 retu
rn 0;25 }1 ssize_t read(int fd, void *buf, size_t count
);2 ssize_t write(int fd, const void *buf, size_t count
);5、综合案例:实现cp命令1 cp b。txt test 将b。txt文件拷贝到test目录中1 #inc
lude <stdio。h>2 #include <unistd。h>3 #include <sys/type
s。h>4 #include <sys/stat。h>5 #include <fcntl。h>6 int ma
in(int argc, char const *argv[])7 {8 //判断参数是否正确(。/a。out
b。txt test)9 if (argc != 3)10 {11 printf("。/a。out b。tx
t test\n");12 return 0;13 }1415 //以只读的方式 打开b。txt文件16 in
t fd_r = open(argv[1], O_RDONLY);17 if (fd_r < 0)18 {19
perror("open");20 return 0;21 }2223 //以写的方式 在test目录中打开
b。txt24 char file_name[32] = "";25 //test/b。txt26 sprin
tf(file_name, "%s/%s", argv[2], argv[1]);27 int fd_w =
open(file_name, O_WRONLY | O_CREAT, 0666);28 if (fd_w <
0)29 {30 perror("open");31 return 0;32 }3334 //不同的从fd_
r中读取文件数据 写入fd_w文件中35 while (1)36 {37 unsigned char buf[
128] = "";38 int len = read(fd_r, buf, sizeof(buf));39
if (len <= 0)40 break;4142 write(fd_w, buf, len);43 pri
ntf("len=%d\n", len);44 }4546 //关闭文件47 close(fd_r);48 c
lose(fd_w);4950 return 0;51 }知识点4【文件的阻塞特性】阻塞和非阻塞 针对的是文件
描述符 而不是read write函数文件描述符 默认 为阻塞的。1、通过open函数 在打开文件的时候 设置
文件描述符为非阻塞。文件描述符 事先不存在 才是用open案例1:open打开文件 默认为阻塞特性案例2:op
en打开文件 设置为非阻塞特性2、通过fcntl设置文件的阻塞特性文件描述符 事先存在1 #include <
unistd。h>2 #include <fcntl。h>3 int fcntl(int fd, int cm
d, 。。。 /* arg */ );功能:改变已打开的文件性质,fcntl针对描述符提供控制。参数:fd:操
作的文件描述符cmd:操作方式arg:针对cmd的值,fcntl能够接受第三个参数int arg。返回值:成功
:返回某个其他值失败:-1fcntl函数有5种功能:1) 复制一个现有的描述符(cmd=F_DUPFD)2)
获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD)3) 获得/设置文件状态标记(cmd=F_G
ETFL或F_SETFL)4) 获得/设置异步I/O所有权(cmd=F_GETOWN或F_SETOWN)5)
获得/设置记录锁(cmd=F_GETLK, F_SETLK或F_SETLKW)设置一个存在的文件描述符的阻塞特
性的步骤1、fcntl获取文件描述符的状态标记2、修改 获取到的 文件描述符的状态标记3、将修改后的状态标记
使用fcntl设置到文件描述符中案例1:设置一个存在的文件描述符的阻塞特性知识点5【获取文件的状态信息】1 #
include <sys/types。h>2 #include <sys/stat。h>3 #include
<unistd。h>4 int stat(const char *path, struct stat *buf
);5 int lstat(const char *pathname, struct stat *buf);功
能:获取文件状态信息stat和lstat的区别:当文件是一个符号链接时,lstat返回的是该符号链接本身的信息
;而stat返回的是该链接指向的文件的信息。参数:path:文件名buf:保存文件信息的结构体返回值:成功:
0失败: -1struct stat结构体说明:1 struct stat {2 dev_t st_dev;
//文件的设备编号3 ino_t st_ino; //节点4 mode_t st_mode; //文件的类型和
存取的权限5 nlink_t st_nlink; //连到该文件的硬连接数目,刚建立的文件值为16 uid_t
st_uid; //用户ID7 gid_t st_gid; //组ID8 dev_t st_rdev; //
(设备类型)若此文件为设备文件,则为其设备编号9 off_t st_size; //文件字节数(文件大小)10
blksize_t st_blksize; //块大小(文件系统的I/O 缓冲区大小)11 blkcnt_t
st_blocks; //块数12 time_t st_atime; //最后一次访问时间13 time_t
st_mtime; //最后一次修改时间14 time_t st_ctime; //最后一次改变时间(指属性
)15 };st_mode(16位整数)参数说明 :案例1:获取文件的属性、大小1 void test03()
2 {3 //获取文件的状态信息4 struct stat s;5 stat("b。txt", &s);67
//分析文件类型(重要)8 if (S_ISREG(s。st_mode))9 {10 printf("为普通文
件\n");11 }12 else if (S_ISDIR(s。st_mode))13 {14 printf(
"为目录文件\n");15 }1617 //获取文件的权限18 if ((s。st_mode & S_IRUS
R) == S_IRUSR)19 {20 printf("所拥有者具备读权限\n");21 }22 if ((
s。st_mode & S_IWUSR) == S_IWUSR)23 {24 printf("所拥有者具备写权
限\n");25 }26 if ((s。st_mode & S_IXUSR) == S_IXUSR)27 {2
8 printf("所拥有者具备执行权限\n");29 }30 }知识点6【文件目录操作】(重要)1、得到文件
目录的句柄1 #include <sys/types。h>2 #include <dirent。h>3 DIR
*opendir(const char *name);4 功能:打开一个目录5 参数:6 name:目录名7
返回值:8 成功:返回指向该目录结构体指针9 失败:NULL2、读取目录1 #include <dirent
。h>2 struct dirent *readdir(DIR *dirp);功能:读取目录 调用一次只能读取
一个文件参数:dirp:opendir的返回值返回值:成功:目录结构体指针失败:NULL相关结构体说明:1 s
truct dirent2 {3 ino_t d_ino; // 此目录进入点的inode4 off_t d_
off; // 目录文件开头至此目录进入点的位移5 signed short int d_reclen; //
d_name 的内容长度, 不包含NULL 字符6 unsigned char d_type; // d_t
ype 所指的文件类型7 char d_name[256]; // 文件名8 };d_type相关数据:3、关
闭目录1 #include <sys/types。h>2 #include <dirent。h>3 int c
losedir(DIR *dirp);功能:关闭目录参数:dirp:opendir返回的指针返回值:成功:0失
败:-11 #include <stdio。h>2 #include <sys/types。h>3 #incl
ude <dirent。h>45 int main(int argc, char const *argv[])
6 {7 //1、获取文件目录句柄8 DIR *dir = opendir("。/");9 if (dir =
= NULL)10 {11 perror("opendir");12 return 0;13 }1415 //
2、读取文件16 struct dirent *ret;17 while (ret = readdir(dir
))18 {19 if ((ret‐>d_type & DT_REG) == DT_REG)20 {21 pr
intf("%s是普通文件\n", ret‐>d_name);22 }23 else if ((ret‐>d_
type & DT_DIR) == DT_DIR)24 {25 printf("%s是目录文件\n", ret
‐>d_name);26 }27 }2829 //3、关闭目录句柄



Disclaimer: The above articles are added by users themselves and are only for typing and communication purposes. They do not represent the views of this website, and this website does not assume any legal responsibility. This statement is hereby made! If there is any infringement of your rights, please contact us promptly to delete it.

字符:    改为:
去打字就可以设置个性皮肤啦!(O ^ ~ ^ O)