Linux C高级编程——文件操作之系统调用
Linux C高级编程文件操作之系统调用
宗旨:技术的学习是有限的,分享的精神是无限的。
库函数是一些完毕特定功能的函数。一般由某个标准组织制作公布,并形成一定的标准。使用库函数编写的函数一般能够应用于不同的平台而不须要做不论什么改动,具有非常好的可移植性。
系统调用函数与操作系统直接相关,不同的操作系统所使用的系统调用可能不太一样,因此,假设两个操作系统差异非常大,系统调用函数的可移植性就不高。
比如windows採用的系统调用的应用程序不能直接在Linux下编译运行。
之所以使用系统调用是由于系统资源的有限性以及内核管理的方便。系统调用将上层内的应用开发与底层的硬件实现分开,上层应用不须要关注底层硬件的详细实现。
Linux的系统调用使用软中断实现,使用系统调用后。该程序的状态将从用户态切换到内核态。库函数实现终于也要调用系统调用函数。但它封装了系统调用操作,从而添加了代码的可移植性。
1、open()函数
——用于打开或者创建一个文件
(1)函数原型:
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int open(constchar* pathname, int flags, ...)
(2)參数
pathname:要创建或者打开的文件名称
flags: 指定文件的打开模式、标志等信息
必须指定一个:O_RDONLY ——仅仅读 O_WRONLY——仅仅写 O_RDWR——读写
可选标志(按位或):O_APPEND——追加
O_TRUNC——若文件存在,读写方式打开或仅仅写打开,则文件长度为0
O_CREAT——若文件不存在。则创建文件,此时,open须要第三个參数。用于指定该 文件的訪问权限(umask能够看掩码)
O_EXCL——若同一时候指定为O_CREAT标志,而文件已经存在。则会出错,可用于文件 是否存在
O_NONBLOCK对于设备文件,以O_NONBLOCK方式打开能够做非堵塞I/O
(3)返回值
整数类型——成功时。返回文件描写叙述符。出错时,返回-1
(4)文件描写叙述符
(文件描写叙述符——已打开文件的索引——通过索引找到已打开文件)
文件描写叙述符是一个非负的整数
文件描写叙述符0,1,2分别表示标准输入,标准输出,标准错误输出,在进程创建时,已经打开。open返回的文件描写叙述符一定是该进程尚未使用的最小描写叙述符
(5)出错处理
errno.h头文件里,定义了errno,当API调用出错时。errno说明出错的详细原因
可简单的将errno理解成整型数据
出错信息转换成可读字符串
#include<string.h>
char* strerror(int errno);
perror函数依据当前的errno,输出一条出错信息(void perror(constchar* msg))
#include<stdio.h>
#include<stdlib.h> #include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h> int main(int argc, char *argv[])
{
int fd;
if(argc < 2)
{
puts("please input the open filepathname!\n");
exit(1);
} //假设flag參数里有O_CREAT表示,该文件假设不存在,系统则会创建该文件,该文 件的权限由第三个參数决定,此处为0755
//假设flah參数里没有O_CREAT參数,则第三个參数不起作用.此时,假设要打开的 文件不存在,则会报错.
//所以fd=open(argv[1],O_RDWR),仅仅仅仅是打开指定文件
if((fd = open(argv[1], O_CREAT | O_RDWR, 0755)) < 0)
{
perror("open filefailure!\n");
exit(1);
}
else
{
printf("open file %d success!\n", fd); }
close(fd); return 0;
}<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
2、 creat()函数
——用于创建一个新文件
(1)函数原型
int creat(const char *pathname,mode_t mode)
(2)參数
pathname:要创建的文件名称(包含路径信息)
mode:同open的第二个參数,讨论文件的訪问权限位时分析:
S_IRUSR——可读 S_IWUSR——可写 S_IXUSR——可运行 S_IRWXU——可读、写、运行
除了用上述宏之外。还能够用数字来表示文件的权限:
可读——4 可写——2 可运行——1 无不论什么权限——0
(3)返回值
成功返回仅仅写打开的文件描写叙述符。出错返回-1
(4)creat函数缺点:它以仅仅写方式打开创建的文件。
若要创建一个暂时文件。并先写该文件,然后又读该文件,则必须先调用creat,close,然后再open.简便方法:
open(pathname,O_RDWR| O_CREAT | O_TRUNC,mode);
#include<stdio.h>
#include<stdlib.h> #include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h> void create_file(char *filename)
{ /*创建的文件具有什么样的属性?*/
if(creat(filename, 0755) < 0)
{
printf("create file %sfailure!\n", filename);
exit(EXIT_FAILURE);
}
else
{
printf("create file %s success!\n", filename);
}
} int main(int argc, char *argv[])
{
int i;
if(argc < 2)
{
perror("you haven't input thefilename,please try again!\n");
exit(EXIT_FAILURE);
} for(i = 1; i < argc; i++)
{
create_file(argv[i]);
} return 0;
}
3、lseek函数(和fseek相似)
——用于改动当前文件偏移量
(当前文件偏移量的作用:规定了从文件什么地方開始进行读、写操作)
——通常,读写操作结束时,会使文件偏移量添加读写的字节数
——当打开一个文件时,除非指定了O_APPEND标志,否则偏移量被设置为0
(1) 函数原型
#include<sys/types.h>
#include<unistd.h>
off_t lseek(int filedes, off_t offset, int whence)
(2) 參数
第一个參数filedes:open/creat函数返回的文件描写叙述符
第二个參数offset:
相对偏移量:需结合whence才干计算出真正的偏移量
类型off_t:通常情况下是32为数据类型
第三个參数whence:该參数取值是三个常量
SEEK_SET:当前文件偏移量为——距文件開始出的offset个字节
SEEK_CUR:当前文件偏移量 + offset(可正可负)
SEEK_END:当前文件长度 + offset(可正可负)
(3)返回值:
成功返回新的文件偏移量。失败返回-1
(4)获取当前的偏移量:
Off_tcurrent_position;
Current_position= lseek(fd,0,SEEK_CUR);
lseek操作并不引起不论什么I/O操作,仅仅是改动内核中的记录(并不引起磁盘的訪问 操作)
(5)空洞文件
——使用lseek改动文件偏移量后。当前文件偏移量有可能大于文件的长度
——在这样的情况下。对该文件的下一次写操作,将加长该文件
——这样文件里形成了一个空洞。对空洞区域进行读,均返回0
4、read函数
——用于从文件里读出数据
(1)函数原型
#include<unistd.h>
ssize_t read(int fd, void *buff, size_t nbytes)
(2)參数
第一个參数fd:文件描写叙述符
第二个參数buff:指向缓冲区。用于存放从文件读出的数据
第三个參数nbytes:unsigned int;须要从文件里读出的字节数
——缓冲区的大小 >= nbytes
(3)返回值
返回值类型:ssize_t,即int
出错返回-1成功:返回从文件里实际读到的字节数,当文件读到结尾时,则返回0
(4)非常多情况下,read实际读出的字节数都小于要求读出的字节数
——读普通文件,在读到要求的字节数之前,就到达了文件尾端
——当从终端设备读时。通常一次最多读一行
——当从网络读时,网络中的缓冲机构可能造成read函数返回值小于所要求读出 的字节数
——某些面向记录的设备。如磁盘,一次最多返回一个记录
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h> #define LENGTH 100 int main(void)
{
int fd, len;
char str[LENGTH];
/* 创建并打开文件 */
fd = open("hello.txt", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if(fd)
{
/* 写入 Hello, software weekly字符串 */
write(fd, "Hello,Software Weekly", strlen("Hello, software weekly"));
close(fd);
}
fd = open("hello.txt", O_RDWR);
len = read(fd, str, LENGTH);/* 读取文件内容 */
str[len] = '\0';
printf("%s\n", str);
close(fd); return 0;
}<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
5、write函数
——用于向文件里面写入数据
(1) 函数原型
#include<unistd.h>
ssize_t write(int fd,const void*buff,size_t nbytes)
(2) 參数
第一个參数fd:文件描写叙述符
第二个參数buff:指向缓冲区。存放了须要写入文件的数据
第三个參数nbytes:须要写入文件的字节数
(3) 返回值
返回值类型:ssize_t,即int
出错返回-1,成功返回实际写入文件的字节数
(4) write出错的原因
——磁盘满
——没有訪问权限
——超过了给定进程的文件长度限制
6、close函数
——用于关闭一个已打开的文件
(1)函数原型
int close(int filedes)
(2) 返回值
成功返回0,出错返回-1
(3)參数
filedes:文件描写叙述符
(4)当close函数关闭文件时,会释放进程加在该文件上的全部记录锁
内核会对进程打开文件表,文件对象,索引节点表项等结构进行改动,释放相关的 资源
当进程退出时,会关闭当前全部已打开的文件描写叙述符
7、ioctl函数
——用于向设备发控制和配置命令(这些数据不能用read/write读写)
(1) 函数原型
#include <sys/ioctl.h>
int ioctl(int d, int request, ...)
(2) 參数
第一个參数d:某个设备的文件描写叙述符
第二个參数request:是ioctl的命令,可变參数取决于request。一般是是一个指向 变量或者结构体的指针
(3)返回值
若出错返回-1,成功返回其它值。取决于request
ioctl(STDOUT_FILENO,TIOCGWINSZ,&size)——获得终端设备的窗体大小
manioctl_list——能够看require的各种參数
8、mmap函数
——能够把磁盘文件的一部分直接映射到内存,这样文件里的位置直接就有相应的内存地址。对文件的读写能够直接用指针来做而不须要read/write函数
(1) 函数原型
#include<sys/mman.h>
void* mmap(void *addr,size_t len,int prot,int flag,int filedes,off_t off)
(2) 參数
addr:NULL——内核会自己在进程地址空间中选择合适的地址建立映射
len:须要映射的那部分文件的长度
off:从文件的什么位置開始映射。必须是页大小的整数倍(32位——4K)
filedes:该文件的文件描写叙述符
prot:
PROT_EXEC——映射的这一段可运行,比如映射的共享库
PROT_READ——映射的这一段可读
PROT_WRITE——映射的这一段可写
PROT_NONE——映射的这一段不可訪问
flag:
MAP_SHARED——多个进程对同一文件的映射是共享的,一个进程对映射的内存做了改动,还有一个进程也会看到这样的变化。
MAP_PRIVATE——多个进程对同一文件的映射不是共享的,一个进程对映射的内存做了改动,还有一个进程不会看到这样的变化。也不会真的写到文件里去。
(3)返回值
成功则返回映射的首地址。出错返回常数MAP_FAILED。
9、access函数
——推断文件能否够进行某种操作
(1)函数原型
int access(const char *pathname,int mode)
(2)參数
pathname:文件名称
mode:推断的訪问权限:R_OK:文件可读 W_OK:文件可写
X_OK:文件可运行 F_OK:文件存在
(3)返回值
成功时。返回0;假设一个条件不符合时。返回-1
10 dup函数
——拷贝文件描写叙述符
(1) 函数原型
#include <unistd.h>
int dup(int oldfd);
(2) 參数
oldfd:待复制的文件描写叙述符
(3)返回值
成功返回新的文件描写叙述符;失败返回-1
11 dup2函数
——拷贝文件描写叙述符
(1) 函数原型
#include <unistd.h>
int dup2(int oldfd, int newfd);
(2) 參数
oldfd:待复制的文件描写叙述符
newfd:新的文件描写叙述符
(3) 返回值
成功返回新的文件描写叙述符;失败返回-1
//小项目:用系统调用函数实现文件拷贝的功能:
/*************************************************************************
> File Name: copy.c
> Author: libang
> Mail: 18211438613@163.com
> Created Time: 2014年07月16日 星期三 00时15分12秒
************************************************************************/ #include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<stdlib.h> int copy_file(intsrc_fd, int dest_fd); int main(intargc, char *argv[]) //注意先搭建主框架
{
if(argc < 3)
{
printf("inputerror!\n");
exit(1);
}
int src_fd, dest_fd; src_fd = open(argv[1], O_RDONLY);
dest_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666);
if(src_fd < 0 | dest_fd < 0)
{
printf("file openfail!\n");
exit(0);
} copy_file(src_fd, dest_fd); printf("success!\n");
close(src_fd);
close(dest_fd); return 0;
} int copy_file(intsrc, int dest)
{
char buf[128];
int r_ret, w_ret;
char *tmp;
//memset(buf,0,128);
printf("success!\n");
while((r_ret = read(src, buf, 128)) > 0) //经典的拷贝算法
{
tmp = buf;
while(r_ret)
{
w_ret = write(dest, tmp, r_ret);
r_ret = r_ret - w_ret;
printf("%d\n", r_ret);
tmp += w_ret;
}
//memset(buf,0,128);
}
printf("success!\n"); return 0;
}
Linux C高级编程——文件操作之系统调用的更多相关文章
- Linux环境高级编程--介绍
从今天開始.将开启Linux环境高级编程(Advanced Programming Of Linux Enviroment)的学习笔记或者说总结,我将持续和大家分享自己的学习成果.本系列博客依托于li ...
- Linux系统编程@文件操作(一)
只总结了部分常用的内容,详细内容参考<UNIX环境高级编程>及相关书籍. Linux中文件编程可以使用两种方法 Linux系统调用(依赖于系统) C语言库函数(不依赖于系统) Linux系 ...
- Linux C 文件操作,系统调用 -- open()、read() 和 标准I/O库 -- fopen()、fread()
函数汇总: open().write().read().close() fopen().fwrite().fread().fclose() 一.什么是文件 在讲述文件操作之前,我们首先要知道什么是文件 ...
- UNIX环境高级编程——文件I/O
一.文件描述符 对于Linux而言,所有对设备或文件的操作都是通过文件描述符进行的.当打开或者创建一个文件的时候,内核向进程返回一个文件描述符(非负整数).后续对文件的操作只需通过该文件描述符,内核记 ...
- Linux C高级编程——网络编程基础(1)
Linux高级编程--BSD socket的网络编程 宗旨:技术的学习是有限的,分享的精神是无限的. 一网络通信基础 TCP/IP协议簇基础:之所以称TCP/IP是一个协议簇,是由于TCP/IP包括T ...
- Linux常见系统命令与文件操作
一.Linux常见文件操作 (1)cd /: 在Linux 系统中斜杠“/”表示的是根目录. cd / ,即进入根目录. (2)cd ~命令是,进入用户在该系统的home目录,例如xz用户,则进入/r ...
- linux常用命令之------文件操作、文件查看、权限、打包压缩
1.一般公司把linux作为自己的应用服务器,将应用和服务器部署在上面 2.测试一般用来打包.压缩.查日志,写一个简单的shell 获得linux服务器的方式 a:网上租一台云服务器 b:安装vmwa ...
- Linux下普通IO文件操作函数---C语言
普通文件IO总结 FILE结构体 typedef struct { int level; /*填充/清空一级缓存*/ unsigned flag; /*文件状态指针*/ ...
- 【Linux】文件操作函数(系统调用函数)
重点在于学习--思路与方法 举一反三 一.文件描述符 系统分配给文件的数字编号 二.函数学习 P.S.Man命令使用方法 manual 前三个章节 命令:系统调用函数:库函数 man read //r ...
随机推荐
- OpenCL学习笔记(一):摩尔定律,异构计算与OpenCL初印象
欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld. 技术交流QQ群:433250724,欢迎对算法.技术.应用感兴趣的同学加入. 关于摩尔定律: 摩尔定律19 ...
- python import模块的搜索路径
当在py代码中import所依赖的模块时, python是从哪里找到这些模块呢,即模块的搜索路径是啥? 默认情况下,Python解释器会搜索当前目录.所有已安装的内置模块和第三方模块,搜索路径存放在s ...
- AC日记——大爷的字符串题 洛谷 P3709
大爷的字符串题 思路: 莫队,需开O2,不开50: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 20000 ...
- thinkphp+dwz完成的一个号码查询小系统
基于网友的例子(http://www.thinkphp.cn/extend/450.html),改进完成一个电话号码查询管理系统.基于thinkphp+dwz完成的电话号码查询小系统,主要改进与功能如 ...
- 多线程IO模型
服务端编程,首要问题是选取IO模型.即如何处理大量连接,服务更多的客户端? 我们最早有2种解法,各有不足: 1.阻塞IO,每个连接都需要一个线程. 随着连接数增多,线程数剧增,系统开销太大. 2.非阻 ...
- 洛谷 P2680 运输计划-二分+树上差分(边权覆盖)
P2680 运输计划 题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条 ...
- STL容器 -- Stack
核心:后进后出, LIFO. 头文件: #include <stack> 常用的构造方法: stack<int> st1; //构造一个空的存放 int 型的栈 stack&l ...
- 货币金额javascript正则表达式
最多保留两位小数,货币金额(不能为0): /^(([1-9]\d*)(\.\d{1,2})?)$|^(0\.0?([1-9]\d?))$/
- 关于 Unity WebGL 的探索(二)
关于 Unity WebGL 的探索(二) 上一篇博客记录了关于 WebGL 移植的第一步:部分 C/C++ 插件的编译,目前项目中的部分插件使用该方法通过,接下来比较大的一部分工作量是网络模块 We ...
- python3中使用xpath无法定位,为什么一直返回空列表?
tbody问题: 在爬去某些网站一些信息的时候,xpath工具上显示类容是正确的,但是在scrapy代码中一直返回空列表 Scrapy的部分代码: class LotteryspiderSpider( ...