Linux C高级编程——文件操作之系统调用

Linux C高级编程文件操作之系统调用


宗旨:技术的学习是有限的,分享的精神是无限的!


 

        库函数是一些完成特定功能的函数,一般由某个标准组织制作发布,并形成一定的标准。使用库函数编写的函数一般可以应用于不同的平台而不需要做任何修改,具有很好的可移植性。

        系统调用函数与操作系统直接相关,不同的操作系统所使用的系统调用可能不太一样,因此,如果两个操作系统差异很大,系统调用函数的可移植性就不高。例如windows采用的系统调用的应用程序不能直接在Linux下编译运行。

        之所以使用系统调用是因为系统资源的有限性以及内核管理的方便,系统调用将上层内的应用开发与底层的硬件实现分开,上层应用不需要关注底层硬件的具体实现。Linux的系统调用使用软中断实现,使用系统调用后,该程序的状态将从用户态切换到内核态。库函数实现最终也要调用系统调用函数,但它封装了系统调用操作,从而增加了代码的可移植性。

 

1open()函数

——用于打开或者创建一个文件

(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;
}
 

3lseek函数(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

 

4read函数

——用于从文件中读出数据

(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 100int 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>

5write函数

——用于向文件里面写入数据

(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出错的原因

——磁盘满

——没有访问权限

——超过了给定进程的文件长度限制

 

6close函数

——用于关闭一个已打开的文件

(1)函数原型

int close(int filedes)

(2) 返回值

成功返回0,出错返回-1

(3)参数

filedes:文件描述符

(4)当close函数关闭文件时,会释放进程加在该文件上的所有记录锁

内核会对进程打开文件表,文件对象,索引节点表项等结构进行修改,释放相关的       资源

当进程退出时,会关闭当前所有已打开的文件描述符                         

 

7ioctl函数

——用于向设备发控制和配置命令(这些数据不能用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的各种参数 

 

8mmap函数

——可以把磁盘文件的一部分直接映射到内存,这样文件中的位置直接就有对应的内存地址,对文件的读写可以直接用指针来做而不需要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。

 

9access函数

——判断文件是否可以进行某种操作

(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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/466791.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解析一个C语言俄罗斯方块游戏,包你看了就会

最近在看俄罗斯方块的游戏&#xff0c;看到一个大神写的俄罗斯方块代码&#xff0c;非常非常优秀&#xff0c;拿出来解析给大家看看&#xff0c;也希望大家自己尝试运行试试&#xff0c;从中能得到一些启发。#先了解下俄罗斯方块的几个形状一共分成 7 形状&#xff0c;有的形状…

认识星座、八大行星的观察

1. 北斗七星 北斗七星属于大熊座&#xff0c;春夏可见&#xff1b;2. 八大行星 太阳系的八大行星基本位于同一轨道面&#xff0c;如以地球轨道面为基准&#xff0c;相互间轨道倾角的差距甚至不到5度&#xff08;不包括水星&#xff09;。太阳系各大行星公转平面与地球黄道平面的…

ERP项目需要持续的呵护

ERP项目需要持续的呵护<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />众所周知&#xff0c;实施ERP是一持续优化的过程&#xff0c;而在这优化完善的过程中&#xff0c;单靠一次实施上线是不够的&#xff0c;尤其是在ERP上线后…

Datawha组队——Pandas(下)综合练习(打卡)

import pandas as pd import numpy as np import missingno as msno import matplotlib.pyplot as plt plt.rcParams[font.sans-serif][SimHei] #用来正常显示中文标签 plt.rcParams[axes.unicode_minus]False #用来正常显示负号#读取数据 df pd.read_csv(端午粽子数据.csv) d…

Linux C高级编程——文件操作之库函数

Linux C高级编程——文件操作之库函数 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的 ——为什么要设计标准I/O库&#xff1f; 直接使用API进行文件访问时&#xff0c;需要考虑许多细节问题 例如&#xff1a;read、write时&#xff0c;缓冲区的大小该如…

【转】spring之任务调度

由于现在大部分的系统都是采用了spring&#xff0c;所以所有的例子都结合spring来构建&#xff0c;目前主要的任务调度分为三种&#xff1a; Java自带的java.util.Timer类&#xff0c;这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执…

测试内存对齐对运行速度的影响

我们知道内存对齐是为了方便CPU工作&#xff0c;但是对齐和不对齐差异有多大呢&#xff1f;我自己也没有实际测试过&#xff0c;今天就运行个代码测试看看。1、1字节对齐的时候#include "stdio.h"#pragma pack(1) struct test { char x1; short x2; float x3; …

连接池的问题

看到关于连接池的问题&#xff0c;觉得很有用&#xff0c;摘录到自己博客上 NET 连接池救生员 防止可淹没应用程序的池溢出 William Vaughn 大多数 ADO.NET 数据提供程序使用连接池&#xff0c;以提高围绕 Microsoft 断开连接的 .NET 结构构建的应用程序的性能。应用程序首先打…

Datawhale-零基础入门NLP-新闻文本分类Task01

参考&#xff1a; https://www.jianshu.com/p/56061b8f463a 统计自然语言处理 宗成庆&#xff08;第二版&#xff09; 文本自动分类简称文本分类(text categorization),是模式识别与自然语言处理密切结合的研究课题.传统的文本分类是基于文本内容的,研究如何将文本自动划分为…

fprintf/fscanf函数分析

fprintf/fscanf函数分析 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 fprintf/fscanf函数与printf/scanf区别&#xff1a;printf/scanf专门针对标准输入输出流&#xff0c;fprintf/fscanf函数可用于任意流&#xff0c;包括输入输出流。 1、fprintf …

华为海选开发者状元?还送14件豪礼?

华为云全年最大 最大 最大开发者庆典活动来啦&#xff01;这次庆典没别的&#xff0c;就是&#xff1a;好玩&#xff01;刺激&#xff01;让你拿奖拿到怀疑人生&#xff01;贺岁就要有贺岁的样子~赶紧来看看华为云为开发者们准备了怎样的新年惊喜好玩的在这里&#xff01;上学的…

国际:如何识别真正的程序员

如何识别优秀的程序员&#xff1f;并不是像听起来那么容易。在这儿工作经验的作用是很有限的&#xff0c;因为伟大的程序员不一定要‘正式’的工作经历来证明他们的伟大。 1&#xff0c;激情。 我曾经遇到许多“职业程序员”&#xff0c;他们从事IT是因为觉得这是一种职业&…

Datawhale-零基础入门NLP-新闻文本分类Task02

Task01里边对赛题进行了分析,接下来进行数据读取与数据分析&#xff0c;通过使用Pandas库完成数据读取和分析操作。 1 数据读取 由赛题数据格式可知&#xff0c;可通过read_csv读取train_set.csv数据&#xff1a; import pandas as pd import numpy as np import matplotlib…

一步步分析-C语言如何面向对象编程

这是道哥的第009篇原创一、前言在嵌入式开发中&#xff0c;C/C语言是使用最普及的&#xff0c;在C11版本之前&#xff0c;它们的语法是比较相似的&#xff0c;只不过C提供了面向对象的编程方式。虽然C语言是从C语言发展而来的&#xff0c;但是今天的C已经不是当年的C语言的扩展…

Linux C高级编程——目录操作

Linux C目录操作 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 Linux思想“一切皆文件”&#xff0c;目录也是文件&#xff0c;只是存储的内容有别于普通文件。目录文件中存储的该目录下所有的文件及子目录文件的信息&#xff0c;inode节点。 一、打开…

利用open***建立桥接***[zt]

利用open***建立桥接***http://blog.chinaunix.net/u/7667/showart_30753.html本文介绍利用open***建立桥接***的一种简单方法&#xff0c;使用的服务器为debian GNU/Linux sarge,使用apt-get dist-upgrade更新到最新&#xff0c;内核2.4.27-1-686&#xff0c;未重新编译内核&a…

c复习过程随笔四

使用scanf函数输入数据&#xff1a;一般形式&#xff08;格式控制&#xff0c;地址表列&#xff09; 格式控制中可以包含普通字符 格式控制和printf函数所遵循的格式相似 使用scanf应注意的问题&#xff1a; &#xff08;1&#xff09;格式控制后面应该是变量地址&#xff0c;而…

Datawhale-零基础入门NLP-新闻文本分类Task03

文本是不定长度的&#xff0c;文本表示成计算的能够运算的数字或向量的方法称为词嵌入&#xff08;Word Embedding&#xff09;。词嵌入是将不定长的文本转换成定长的空间中。为了解决将原始文本转成固定长度的特征向量问题&#xff0c;scikit-learn提供了以下方法&#xff1a;…

Linus 在圣诞节想提前放假做了这些解释,哈哈哈

最近在 lkml.org 上看到Linus发布的一个信息&#xff0c;挺有意思的&#xff0c;我看了内容&#xff0c;然后根据自己的理解展示给大家看看&#xff0c;如果有不对的地方欢迎指正。好的&#xff0c;5.10内核发布了我真希望在圣诞节来的最后一个星期没有那么多破事&#xff0c;现…

文件流、目录流、文件描述符总结

文件流、目录流、文件描述符总结 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 内核为使当前进程与进程打开的文件建立联系&#xff0c;在进程PCB&#xff08;一个结构体task_struct&#xff09;中使用一个成员来指向关于打开文件列表的结构体struct …