linux下 文件IO 相关
linux下操作文件或设备,需要一个文件描述符 file descriptor,fd 来引用。fd是一个非负整数,实际上是一个索引值,指向文件的记录表,对文件的操作都需要fd。默认的几个:标准输入流 STDIN_FILENO 实际为0;标准输出流 STDOUT_FILENO 实际为1;标准错误流 STDERR_FILENO 实际为2。下面介绍几个文件操作相关函数:open close read write lseek fcntl
1、open
#include <sys/types.h>//提供pid_t定义
#include <sys/stat.h>
#include <fcntl.h> int open(char *filepath, int flag, int perms)
/*
* flags: O_RDONLY(只读)
* O_WRONLY(只写)
O_RDWR(读写)
O_CREAT(若文件不存在则创建)
O_EXCL(若使用O_CREAT时文件已存在,则返回错误,用来验证文件是否存在)
O_TRUNC(先删除文件原内容)
O_NOCTTY
O+APPEND(以追加方式打开,文件指针指向文件末尾)
除前三个外,其余可以相互|组合;
perms 文件权限; 成功返回fd,失败返回-1;
*/
2、close
#include <unistd.h> int close(int fd)
/*
成功返回 0 失败返回-1
*/
3、read
#include <unistd.h> ssize_t read(int fd, void *buf, size_t count)
/*
读完一行 或 读到count个byte,返回
成功返回读到的字节数;读到文件末尾返回0 失败返回-1
*/
4、write
#include <unistd.h> ssize_t write(int fd, void *buf, size_t count)
/*
成功返回已写的字节数
失败返回-1
*/
5、lseek
#include <unistd.h>
#include <sys/types.h> off_t lseek(int fd, off_t offset, int whence)
/*
移动文件指针,whence为基准,取值为SEEK_SET:文件开头;SEEK_CUR:当前位置;SEEK_END:文件末尾。实际偏移值为 offset+whence offset可正可负。
成功返回当前位置
失败返回-1
*/
6、fcntl
fcntl函数的其中一个功能是用来给文件加锁,给文件的某一记录加的锁成为记录锁,记录锁又分为读取锁和写入锁。读取锁又称为共享锁,它能够使多个进程都能在文件的同一部分建立读取锁;写入锁又称为排斥锁,任何时候只能有一个进程在文件的某个部分上建立写入锁。文件的同一部分不能同时建立读取锁和写入锁。
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h> int fcntl(int fd, int cmd, struct flock *lock)
/*
cmd: F_DUPFD 复制fd;
F_SETFD
F_GETFD
F_GETFL 得到open时设置的标志
F_SETFL 设置open时设置的标志
F_GETLK 根据lock的描述决定是否上文件锁
F_SETLK 设置lock的文件锁
F_SETLKW
F_GETOWN 检索将收到SIGIO或SIGURG信号的进程号或进程组号
F_SETOWN 设置进程号或进程组号
struct flock
{
short l_type;
off_t l_start;
short l_whence;
off_t l_len;
pid_t l_pid;
}
l_type可取 F_RDLCK读取锁;F_WRLCK写入锁;F_UNLCK解锁。
加锁区域为从l_start+l_whence开始,l_len长度的区域。加锁整个文件的做法通常为l_start为0, l_whence为SEEK_SET,l_len为0.
成功返回0 失败返回-1
*/
文件加锁实例:
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h> void lock_set(int fd, int type)
{
struct flock lock;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0; while(1)
{
lock.l_type = type;
if(fcntl(fd, F_SETLK, &lock)==0)
{//lock set successful
if(lock.l_type==F_RDLCK)
printf("set read lock by pid %d.\n", getpid());//current pid
else
if(lock.l_type==F_WRLCK)
printf("set write lock by pid %d.\n", getpid());
else
if(lock.l_type==F_UNLCK)
printf("release lock by pid %d.\n", getpid()); return;
} /*set lock failed, print why and wait usr press any key to set lock again*/
fcntl(fd, F_GETLK, &lock);
if(lock.l_type!=F_UNLCK)
{
if(lock.l_type==F_RDLCK)
printf("read lock already set by pid %d.\n", lock.l_pid);
else
if(lock.l_type==F_WRLCK)
printf("write lock already set by pid %d.\n", lock.l_pid); getchar();
}
}
}
读取锁是共享的,一个进程加锁后,还允许其他进程加锁;写入锁是互斥的,同一时间只允许一个进程加锁。
7、select
IO多路转接模型,应用于IO复用。
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h> int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exeptfds, struct timeval *timeout)
numfds:监视的最高文件描述符+1;
readfds:监视的读文件描述符集合;
writefds:监视的写文件描述符集合;
exepetfds:监视的异常处理文件描述符集合;
timeout:NULL表示永远等待直到捕捉到信号,0表示从不等待,立即返回。
成功返回准备好的文件描述符,失败返回-1.
相关的几个操作宏:
FD_ZERO(fd_set *fds)//清除文件描述符集
FD_SET(int fd, fd_set *fds)//将fd加入到fds中
FD_CLR(int fd, fd_set *fds)//将fd从fds中清除
FD_ISSET(int fd, fd_set *fds)//判断fds中fd是否变化
另:struct timeval
struct timeval
{
long tv_sec;
long tv_unsec;//microsecond 1/1000000 s
}
一个select实现IO多路转接的实例:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h> int select_test()
{
int fd_read, fd_write;
int ret;
fd_set readfds, writefds;
struct timeval tv; if((fd_read = open("xxx.c", O_RDWR|O_CREAT, 0666))<0)
perror("open read.\n");
if((fd_write = open("ooo.c", O_RDWR|O_CREAT, 0666))<0)
perror("open write.\n"); lseek(fd_read, 0, SEEK_SET); FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_SET(fd_read, &readfds);
FD_SET(fd_write, &writefds); tv.tv_usec = 0;
tv.tv_sec = 2; while(FD_ISSET(fd_read, &readfds)||FD_ISSET(fd_write, &writefds))
{
ret = select(fd_write+1, &readfds, &writefds, NULL, &tv);
if(ret < 0)
perror("select");
else
{
if(FD_ISSET(fd_read, &readfds))
{
//read fd_read
}
if(FD_ISSET(fd_write, &writefds))
{
//write fd_write
}
}
} return 0;
}
以上的文件操作是基于文件描述符的基本的IO控制,是不带缓存的, 属于POSIX标准。下面介绍ANSI C标准的IO处理,是基于流缓冲的。ANSIC C标准提供三种类型的缓冲存储:全缓冲 (当填满缓存后才执行实际IO操作);行缓冲 (当遇到换行字符时才执行实际IO操作);不带缓冲(stderr流通常是不带缓冲的)。下面介绍相关操作函数:
1、fopen fdopen freopen
成功都返回FILE类型指针,失败返回NULL。参数不同。
mode取值:
r或rb:打开只读文件,该文件必须存在;
w或wb:打开可读写文件,该文件必须存在;
w+或w+b:打开可读写文件,若文件存在则文件长度清为0,若文件不存在则建立该文件;
a或ab:以附加方式打开只写文件,若文件不存在则先建立该文件,否则数据加到原文件末尾;
a+或a+b:以附加方式打开可读写文件,若文件不存在则建立该文件,否则数据加到原文件末尾;
b用来说明打开的文件为二进制文件。
2、fclose
成功返回0, 失败返回EOF
3、fread
#include <stdio.h> size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
/*
成功返回读取到的数,失败返回EOF
*/
4、fwrite
#include <stdio.h> size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
/*
成功返回实际写入的数,失败返回EOF
*/
5、几个输入输出函数
#include <stdio.h> int getc(FILE *stream)
int fgetc(FILE *stream)
int getchar(void)
/*成功返回字符失败返回EOF*/
int putc(int c, FILE *stream)
int fputc(int c, FILE *stream)
int putchar(int c)
/*成功返回c,失败返回EOF*/
char *fgets(char *s, int size, FILE *stream)
char *gets(char *s)
/*
成功返回s失败返回NULL
*/
int puts(const char *s)
int fput(const char *s, FILE *stream)
差不多了,下面研究下linux下串口应用程序开发
关于串口本身不想多说,linux中,串口对应的设备名为/dev/ttyS0、/dev/ttyS1.。。分别对应串口1、串口2.。。。linux下对设备的操作方法与对文件的操作方法完全一样,因此对串口的读写就是read write等,对串口的一些参数需要另做配置,这是不同之处。
linux下串口的设置主要是设置struct termios
#include <termios.h> struct termios
{
unsigned short c_iflag;//输入模式标志
unsigned short c_oflag;//输出模式标志
unsigned short c_cflag;//控制模式标志
unsigned short c_lflag;//本地模式标志
unsigned char c_line;//line discipline
unsigned char c_cc[NCC];//control char
}
通常是这样的:
int set_opt(int fd, int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios newtio, oldtio; if(tcgetattr(fd, &oldtio)!=0)
{
perror("set serial.");
return -1;
}
bzero(&newtio, sizeof(newtio)); /*set serial*/ /*step 1:设置字符大小*/
newtio.c_cflag |= CLOCAL|CREAD;
newtio.c_cflag &= ~CSIZE; /*step 2:设置停止位*/
switch(nBits)
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
} /*step3:设置奇偶校验位*/
switch(nEvent)
{
case 'O':
/*奇校验*/
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_cflag |= INPCK|ISTRIP;
break;
case 'E':
/*偶校验*/
newtio.c_cflag |= INPCK|ISTRIP;
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'N':
/*无校验*/
newtio.c_cflag &= ~PARENB;
break;
} /*step4: 设置波特率*/
switch(nSpeed)
{
/*不能直接操作c_cflag,使用特定函数*/
case 2400:
cfsetispeed(&newtio, B2400);//接收波特率
cfsetospeed(&newtio, B2400);//发送波特率
break;
case 4800:
cfsetispeed(&newtio, B4800);
cfsetospeed(&newtio, B4800);
break;
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
case 460800:
cfsetispeed(&newtio, B460800);
cfsetospeed(&newtio, B460800);
break;
default:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
} /*step5:设置停止位*/
if(nStop==1)
newtio.c_cflag &= ~CSTOPB;
else
if(nStop==2)
newtio.c_cfalg |= CSTOPB; /*stcp6:设置等待时间和最小接收字符*/
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0; /*处理未接收字符*/
tcflush(fd, TCIFLUSH); /*激活新配置*/
if((tcsetattr(fd, TCSANOW, &newtio))!=0)
{
perror("set serial");
return -1;
} return 0;
}
而打开串口通常是这样的:
int open_port(int comport)
{
char *dev[] = {"/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2"};
long vdisable;
int fd;
char *comdev = NULL; if(comport==1)
/*串口1*/
comdev = "/dev/ttyS0";
if(comport==2)
comdev = "/dev/ttyS1";
if(comport==3)
comdev = "/dev/ttyS2"; if(comdev==NULL)
return -1; if((fd = open(comdev, O_RDWR|O_NOCTTY|O_NDELAY))<0)
return -1; /*恢复串口阻塞状态*/
if(fcntl(fd, F_SETFL, 0)<0)
printf("fcntl failed.\n"); /*测试是否为终端设备*/
if(isatty(STDIN_FILENO)==0)
printf("standard input is not a terminal device.\n");
else
printf("isatty success.\n"); return fd;
}
测试一下:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h> int com_test()
{
int fd;
int nread, i; if((fd = open_port(1))<0)
{
perror("open port failed.");
return -1;
}
if((i = set_opt(fd, 115200, 8, 'N', 1))<0)
{
perror("set port failed.");
return -1;
} //read(fd, buf, 8); close(fd);
return 0;
}
嗯 先这样吧
linux下 文件IO 相关的更多相关文章
- Linux下的IO监控与分析
Linux下的IO监控与分析 近期要在公司内部做个Linux IO方面的培训, 整理下手头的资料给大家分享下 各种IO监视工具在Linux IO 体系结构中的位置 源自 Linux Performan ...
- Linux下文件的权限
一.Linux下查看文件属性 命令为: [root@localhost ~]# ls -al 结果: ls是『list』的意思,重点在显示文件的文件名与相关属性.而选项『-al』则表示列出所有的文件详 ...
- Windows与Linux下文件操作监控的实现
一.需求分析: 随着渲染业务的不断进行,数据传输渐渐成为影响业务时间最大的因素.究其原因就是因为数据传输耗费较长的时间.于是,依托于渲染业务的网盘开发逐渐成为迫切需要解决的需求.该网盘的实现和当前市场 ...
- LINUX下文件编译
body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2p ...
- 常见压缩格式分析,及 Linux 下的压缩相关指令
可先浏览加粗部分 一.常见压缩档 *.zip | zip 程式壓縮打包的檔案: (很常见,但是因为不包含文件名编码信息,跨平台可能会乱码) *.rar | winrar 程序压缩打包的档案:(在win ...
- Linux 下文件
Linux下文件的三个时间(Atime,Mtime,Ctime) [root@node ~]# stat install.log File: `install.log' Size: Blocks: ...
- Linux下文件的三个时间意义及用法
Linux下文件的三个时间参数: (1)modification time(mtime):内容修改时间 这里的修改时间指的是文件的内容发生变化,而更新的时间. (2)change tim ...
- (转)linux下文件删除的原理精华讲解(考试题答案系列)
linux下文件删除的原理精华讲解(考试题答案系列) 说明:本文为老男孩linux培训某节课前考试试题及答案分享博文内容的一部分,也是独立成题的,你可以点下面地址查看全部的内容信息.http://ol ...
- linux中文件IO
一. linux常用文件IO接口 1.1. 文件描述符 1.1.1. 文件描述符的本质是一个数字,这个数字本质上是进程表中文件描述符表的一个表项,进程通过文件描述符作为index去索引查表得到文件表指 ...
随机推荐
- javascript笔记整理(事件)
一.事件驱动 1.事件javascript侦测到的用户的操作或是页面的一些行为(怎么发生的) 2.事件源引发事件的元素(发生在谁的身上) 3.事件处理程序对事件处理的程序或是函数 (发生了什么事) 二 ...
- Qt调用DLL
声明: 事先我已经自己动手写了一个简单的dll文件(myDLL.dll),C版接口的.并且用我前两篇有关DLL文章里面的方法,从dll中导出了导入库(.lib)文件,dll中有两个函数,原型如下: ...
- 解决QT Creator在Linux下的输入法问题
https://vjudge1.github.io/2014/04/02/type-chinese-in-linux/http://blog.csdn.net/ubuntutouch/article/ ...
- WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于WS-MEX的实现](提供模拟程序)
原文:WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于WS-MEX的实现](提供模拟程序) 通过<如何将一个服务发布成WSDL[编程篇]>的介绍我们知道了如何可以通过编程或者配 ...
- [思路]为什么要做一个Web服务器
对于.net开发者而言,提到Web服务器最容易想到的就是IIS了. IIS功能强大,配置繁多,但不免对普通用户而言过于复杂,另外在云时代的今天,同时维护多个IIS或远程维护IIS还是有诸多不便的,有很 ...
- [HTML5实现人工智能]小游戏《井字棋》发布,据说IQ上200才能赢
一,什么是TicTacToe(井字棋) 本 游戏 为在下用lufylegend开发的第二款小游戏.此游戏是大家想必大家小时候都玩过,因为玩它很简单,只需要一张草稿纸和一只笔就能开始游戏,所以广受儿 ...
- android的四种加载模式
在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.在Android中Activity的启动模式决定了Activity的启动运行方式. An ...
- PHP - 图像处理
第14章 处理图像 学习要点: 1.创建图像 2.简单小案例 在PHP5中,动态图象的处理要比以前容易得多.PHP5在php.ini文件中包含了GD扩展包,只需去掉GD扩展包的相应注释就可以正常使用了 ...
- Cocos2D-X学习笔记 3 从一个场景切换到还有一个场景
工厂方法一般写法 StartLayer * StartLayer::create() { StartLayer *sl = new StartLayer(); sl->init(); sl-&g ...
- EasyUI - 一般处理程序 返回 Json值
使用 一般处理程序(ashx)返回Json值. 原始Json数组的格式: [ { ", "name":"张三", "sex":&q ...