100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > Linux文件系统【02】creat open close read write lseek;ioctl fcntl dup dup2 自定义创建文件命令

Linux文件系统【02】creat open close read write lseek;ioctl fcntl dup dup2 自定义创建文件命令

时间:2020-02-21 12:55:03

相关推荐

Linux文件系统【02】creat open close read write lseek;ioctl fcntl dup dup2 自定义创建文件命令

目录

前言

1, open()

2,creat()

3, close()

4,自己写创建文件的命令(可以附加上权限设置,期待后续)

5, read()

6, write()

7, lseek()

8, dup、dup2

9, fcntl

10, ioctl

前言

fopen,fclose,fread,fwrite,fseek;是C语言标准库的,方便移植;

文件的创建,打开,关闭,读,写,光标:

creat,open,close,read,write,lseek;

什么是文件描述符?

文件描述符是Unix特有的,其为一个非负整数,取值范围是0-NR_OPEN,对于Linux,NR_OPEN=255;也就是每个程序只能打开256 个文件;当使用open或者creat打开或者创建一个文件的时候,如果成功则将返回一个文件描述符,在进行读写操作时(read/write),文件描述符作为参数传递给(read/write);

文件描述符0代表标准输入文件,一般就是键盘,1代表标准输出文件,一般就是显示器,2代表标准错误输出,一般也是显示器;

1, open()

#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>int open(const char *pathname,int flags);int open (const char *pathname,int flags,mode_t mode);

pathname,含路径的文件名

flags文件打开方式:

这三种只能三选一。

O_SYNC,O_NONBLOCK,O_NDELAY同步异步阻塞非阻塞等等(待解决)

当使用O_CREAT时,才使用参数mode,用来说明新文件的权限(权限实际上是mode||umask),mode的取值:

2,creat()

#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>int creat(const char *pathname , mode_t mode);

创建或者覆盖原有文件

pathname,含路径的文件名

mode与open的相同

3, close()

#include<unistd.h>int close(int fd);

fd:文件描述符。

调用成功返回0,失败返回-1;

不保证数据全部存回硬盘。

4,自己写创建文件的命令(可以附加上权限设置,期待后续)

#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<stdio.h>#include<unistd.h>#include<errno.h>int main(int argc,char ** argv){int fd;char *path;if(argc<2){printf("%s<mode num><target file>\n",argv[0]);_exit(0);}path=argv[1];if((fd=open(path,O_CREAT|O_EXCL,S_IRUSR|S_IWUSR))==-1){perror("open");_exit(1);}else{printf("creat a file success");}close(fd);return 0;}

5, read()

#include<unistd.h>ssize_t read(int fd, void *buf,size_t count);

从文件描述符所指向的文件中读取count个字符到buf所指向的缓存中。

当count=0,read不读取数据,只返回0;

读取成功返回读取到的字节数,与count作比较,如果返回字节数目比count少,则是读到了文件末尾或者读取过程中信号被中断了等等。读取失败则返回-1;存到errno中;

文件读写指针随着读写移动;

6, write()

#include<unistd.h>ssize_t write(int fd, void *buf,size_t count);

将buf指向的缓冲区中的count个字节写到fd所指示的文件当中。

返回写入的字节数

错误返回-1,存到errno中;

7, lseek()

#include<sys/types.h>#include<unistd.h>off_t lseek(int fildes,off_t offset,int whence);

lseek()用来控制该文件的读写文件;

参数fildes为已经打开的文件的文件描述符;

参数offset为根据whence来移动读写位置的位移数;

参数whence:

lseek允许文件指针的值设置到文件结束符(EOF)之后,但并不会改变文件大小,在此位置写入数据之后,此段数据与之前的(EOF)之间是数据0;

有些设备文件不能使用lseek,比如Linux的tty文件,用lseek会返回错误代码ESPIPE;

#include<stdio.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>#include<errno.h>#include<string.h>//报错函数void my_err(const char *err_string,int line){fprintf(stderr,"line:%d",line);perror(err_string);_exit(1);}//读数据函数int my_read(int fd){int len;int ret;int i;char read_buf[64];//指针移到最后if(lseek(fd,0,SEEK_END)==-1){my_err("lseek",__LINE__);}//最后位置到文件开始位置字节数if((len=lseek(fd,0,SEEK_CUR))==-1){my_err("lseek",__LINE__);}//指针回到文件开始处,下一步方便读取数据if(lseek(fd,0,SEEK_SET)==-1){my_err("lseek",__LINE__);}printf("len:%d\n",len);//读取数据,返回读取字节数if((ret=read(fd,read_buf,len))<0){my_err("read",__LINE__);}//打印for(i=0;i<len;i++){printf("%c",read_buf[i]);}printf("\n");return ret;}int main(){int fd;char write_buf[32]="Hello World";char write_buf2[32]="Q";if((fd=open("test.txt",O_CREAT|O_RDWR|O_TRUNC,S_IRUSR|S_IWUSR))==-1){my_err("open",__LINE__);}else{printf("creat the file success\n");}if(write(fd,write_buf,strlen(write_buf))!=strlen(write_buf)){my_err("write",__LINE__);}printf("---------------------------------\n");if(lseek(fd,10,SEEK_END)==-1){my_err("lseek",__LINE__);}if(write(fd,write_buf2,strlen(write_buf2))!=strlen(write_buf2)){my_err("write",__LINE__);}my_read(fd);close(fd);return 0;}

__LINE__内置宏,提示错误位置

类似还有__TIME__,__FUNCTION__,__FILE__等等;

8, dup、dup2

都是用于复制文件描述符(意义不同于平时的复制文本)

#include<unistd.h>int dup(int oldfd);int dup2(int oldfd,int newfd);

dup成功返回最小尚未被使用的文件描述符,失败返回-1;新文件描述符等同于旧文件描述符;

dup2返回指定的文件描述符newfd;newfd被占用时先释放newfd,再复制,当oldfd=newfd时,不释放。成功返回newfd,失败返回-1。

输入输出重定向?

9, fcntl

对已经打开的文件描述符进行操作改变其各种属性

#include<unistd.h>#include<funtl.h>int fcntl(int fd,int cmd);int fcntl(int fd,int cmd,long arg);int fcntl(int fd,int cmd,struct flock *lock);

参数cmd:

(a)F_DUPFD。同dup

(b)F_GETFD。获取文件描述符的close-on-exec标志,成功返回标志值,若其最后一位为0,则表示执行exec相关函数之后文件描述符韩式打开的,不然则是已经该关闭文件描述符;失败返回-1。

(c)F_SETFD。将close-on-exec标志为arg的最后一位,成功返回0,失败返回-1;

(d)F_GETFD。获取文件打开方式。成功返回标志值失败返回-1。见open的参数flags。

(e)F_SETFD。设置打开方式为arg的指定方式(O_APPEND,O_NONBLOCK与O_ASYNC之一)。见open参数flags。

例子:

#include<stdio.h>#include<unistd.h>#include<fcntl.h>#include<sys/types.h>#include<sys/stat.h>void my_err(const char *err_string,int line){fprintf(stderr,"line:%d",line);perror(err_string);_exit(1);}int main(){int ret;int access_mode;int fd;if((fd=open("test.txt",O_RDONLY))==-1){my_err("open",__LINE__);}if((ret=fcntl(fd,F_GETFL,0))<0){my_err("fcntl",__LINE__);}access_mode=ret&O_ACCMODE;if(access_mode==O_RDONLY){printf("test.txt access mode:read only");}else if(access_mode==O_WRONLY){printf("test.txt access mode:read only");}else if(access_mode==O_RDWR){printf("test.txt access mode:read + write");}if(ret&O_APPEND){printf(" ,append");}if(ret&O_NONBLOCK){printf(" ,nonblock");}if(ret&O_SYNC){printf(" ,sync");}printf("\n");return 0;}

测试结果:

(f)F_GETLK。参数lock指向一个希望设置的锁的结构体,如果目标位置的锁能够被设置,那么修改结构体的i_type为U_UNLCK,然后返回。如果目标位置有锁且冲突,那么返回一个冲突的锁的结构。

(g)F_SETLK。设置或者释放锁。i_type为F_RDLCK或者F_WRLCK时,指定区域设置锁,当i_type时释放锁。当锁被其他进程占用时,返回-1,且设置errno为EACCES或者EAGAIN。注意文件的打开方式要相应,例如设置读锁要以可读方式打开

(h)F_SETLKW。功能与F_SETLK相似,不过当有其他锁存在而被阻值时,会等待冲突的锁被释放

(i)F_GETOWN

(j)F_SETOWN

(k)F_SETSIG

(l)F_GETSIG

10, ioctl

用来控制设备

#include<sys/ioctl.h>int ioctl(int fd,int request,...);

第三个参数一般为char *argp,其随reques不同而不同,request决定argp是向ioctl传递数据还是获取数据。

#include<stdio.h>#include<unistd.h>#include<sys/ioctl.h>#include<stdlib.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<sys/types.h>#include<net/if.h>#include<string.h>unsigned char g_macaddr[6];unsigned int g_subnetmask;unsigned int g_ipaddr;unsigned int g_broadcast_ipaddr;void init_net(void){int i;int sock;struct sockaddr_in sin;struct ifreq ifr;char g_eth_name[16];sock=socket(AF_INET,SOCK_DGRAM,0);if(sock==-1){perror("socket");}strcpy(g_eth_name,"ens33");//注意ens33,应该ifconfig一下在决定是什么,未知原因,没学到网络编程,后续补充strcpy(ifr.ifr_name,g_eth_name);printf("eth name:\t%s\n",g_eth_name);if(ioctl(sock,SIOCGIFHWADDR,&ifr)<0){perror("ioctl");}memcpy(g_macaddr,ifr.ifr_hwaddr.sa_data,6);printf("local mac:\t");for(i=0;i<5;i++){printf("%.2x:",g_macaddr[i]);}printf("%.2x:\n",g_macaddr[i]);if(ioctl(sock,SIOCGIFADDR,&ifr)<0){perror("ioctl");}memcpy(&sin,&ifr.ifr_addr,sizeof (sin));g_ipaddr=sin.sin_addr.s_addr;printf("local eth0:\t%s\n",inet_ntoa(sin.sin_addr));if(ioctl(sock,SIOCGIFBRDADDR,&ifr)<0){perror("ioctl");}memcpy(&sin,&ifr.ifr_addr,sizeof (sin));g_broadcast_ipaddr=sin.sin_addr.s_addr;printf("broadcast:\t%s\n",inet_ntoa(sin.sin_addr));if(ioctl(sock,SIOCGIFNETMASK,&ifr)<0){perror("ioctl");}memcpy(&sin,&ifr.ifr_addr,sizeof (sin));g_broadcast_ipaddr=sin.sin_addr.s_addr;printf("subnetmask:\t%s\n",inet_ntoa(sin.sin_addr));close(sock);}int main(){init_net();return 0;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。