Linux环境编程之一

0. 前言

本文主要是想整理一下linux环境编程的一些接口,包括一些系统调用,以及更多的glibc的库函数,并不对其中原理进行限制,属于工具字典类型,面向使用。

本文主要参考:《Linux环境编程:从应用到内核》

1. 文件I/O

打开open

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

第1个参数pathname:表示要打开的文件路径;

第2个参数flags:用于指示打开文件的选项,常用的有O_RDONLY(0:只读)、 O_WRONLY(1:只写)和O_RDWR(2:读写),另外还有:

选项含义
O_APPEND每次写操作,内核都会先定位到文件尾
O_ASYNC使用异步I/O模式
O_CLOEXECfork时,子进程关闭文件
O_CREATE当文件不存在时,就创建文件
O_EXCL标志本次操作是创建,与O_CREATE连用;当文件存在,返回失败
O_NONBLOCK将文件描述符设置为非阻塞的
O_SYNC设置为I/O同步模式,每次写操作都会将数据同步到磁盘
O_TRUNC打开文件时,文件长度截断为0

第3个参数mode:只有在创建文件时需要,用于指定所创建文件的权限位

创建create

int creat(const char * pathname, mode_tmode);

create函数用于创建新文件,其等价于open(pathname,O_WRONLY|O_CREAT|O_TRUNC,mode)

关闭close

int close(int fd);

成功返回0,失败返回-1;用于关闭文件描述符。文件描述符可以是普通文件,也可以是设备,还可以是socket,VFS会根据不同的文件类型,执行不同的操作。

文件偏移lseek

off_t lseek(int fd, off_t offset, int whence);

描述:将fd的文件偏移量设置为以whence为起点,偏移为offset的位置。

第3个参数whence:可以为SEEK_SET(文件起始位置)、SEEK_CUR( 文件当前位置)、SEEK_END(文件的末尾)。

返回新的文件偏移量。当执行成功时,它会返回最终以文件起始位置为起点的偏移位置。如果出错,返回-1,同事errno被设置为对应的错误值。

但对于某些设备,它允许返回负的偏移量,这时候就需要同时判断errno与返回值。

读取read

ssize_t read(int fd, void *buf, size_t count);

描述:从fd中读取count字节到buf中,并返回成功读取的字节数,同时将文件偏移向前移动相同的字节数。返回0的时候表示已经到了文件末尾。

read返回值为-1,如果errno为EAGAIN、EWOULDBLOCK或者EINTR,一般不能视为错误。前两者为fd为非阻塞且没有数据可读时返回,后者是read被信号中断。

写入write

ssize_t write(int fd, const void *buf, size_t count);

描述:从buf指向的地址读取count字节,写入到文件描述符fd中,并返回成功写入的字节数,同事将文件偏移向前移动相同的字节数。

文件描述符复制dup

int dup(int oldfd);
int dup2(int oldfd, int newfd);
int dup3(int oldfd, int newfd, int flags);

dup:户使用一个最小的未用的文件描述符作为复制后的文件描述符。

dup2:使用用户制定的文件描述符newfd来复制oldfd的。如果newfd已经是打开的,linux会先关闭newfd。

dup3:多一个flags,目前只支持O_CLOEXEC,避免将文件内容暴露给子进程。

文件数据的同步sync

void sync(void);
int fsync(int fd);
int fdatasync(int fd);

描述:linux会对文件的I/O操作进行缓存,对于读操作,如果内容已经在文件缓存中,就直接读取文件缓存。对于写操作,会先将修改提交到文件缓存中,在合适的时机持久化到磁盘。以上函数会同步缓存中数据到磁盘。

后两者只同步fd指定的文件,并直到同步完成才返回。

文件元数据stat

int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);

描述:3个函数用户得到文件的基本信息,区别在于stat得到路径path所指定的文件基本信息,fstat得到文件描述符fd指定文件的基本信息,lstat与stat基本相同,当path是一个连接文件时,lstat得到是连接文件本身的基本信息,而不是指向文件的信息。

文件的截断truncate

int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);

含义相同,参数不同,一个是路径,一个是fd。截断可以是缩小,也可以是放大,将文件大小变成length。

2. 标准I/O库

打开fopen

FILE *fopen(const char *filename, const char *mode)

第1个参数filename:要打开的文件路径

第2个参数mode:

fopen标志位open标志位用途
rO_RDONLY以只读方式打开文件
r+O_RDWR以读写方式打开
wO_WRONLY | O_CREATE | O_TRUNC以写方式打开:文件存在,截断为0;当文件不存在,创建该文件
w+O_RDWR | O_CREATE | O_TRUNC以读写方式打开:文件存在,截断为0;当文件不存在,创建该文件
aO_WRONLY | O_APPEND | O_CREATE以追加写的方式打开文件,当文件不存在时,创建该文件
a+O_RDWR | O_APPEND | O_CREATE以追加读写的方式打开文件,当文件不存在时,创建该文件

返回FILE,表示文件流

打开fdopen与fileno

FILE *fdopen(int fd, const char *mode);
int fileno(FILE *stream);

linux提供了文件描述符,c库提供了文件流。以上2个函数是在这两者之间 的切换。

fdopen用于从文件描述符生成一个文件流FILE

fileno用于从文件流FILE得到对应的文件描述符

关闭fclose

int fclose(FILE *stream);

关闭文件,用fopen、fdopen打开的文件都需要用它来关闭文件。因为只有采用这种方式,fclose作为c库函数,才会释放文件流FILE占用的内存。

读取fget 和 getc

int fgetc(FILE *stream);
int getc(FILE *stream);

返回下一个字符,返回值是int,原因是到了文件末尾,会返回EOF,而EOF是一个int类型的负数。

读取与写入fread和fwrite

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

第1个参数ptr:指向要读取或写入的数据。

第2个参数size是长度。

第3个参数:nmemb用于指示fread和fwrite要执行的对象个数。

第4个参数:stream是目标的文件。

注意他们的返回值,返回的是成功读取或写入的多少个size大小的对象。

创建临时文件tmpnam

FILE *tmpfile(void);
int mkstemp(char *template);

描述:tmpfile返回一个以读写模式打开的、唯一的临时文件流指针。当文件指针关闭或程序正常结束时,该临时文件会被自动删除。

这个临时文件只能生成在固定的路径(/tmp)下,并且有可能因为文件名冲突而失败返回NULL。

mkstemp 会根据template创建并打开一个独一无二的临时文件。template的最后6个字符必须是XXXXXXX。glibc会生成一个独一无二的后缀来替换它。成功后会返回临时文件的文件描述符,失败时返回-1。

几个示例

#include <stdio.h>

int main () {
   FILE *fp;
   int c;
   int n = 0;
  
   fp = fopen("file.txt","r");
   if(fp == NULL) {
      perror("Error in opening file");
      return(-1);
   } do {
      c = fgetc(fp);
      if( feof(fp) ) {
         break ;
      }
      printf("%c", c);
   } while(1);

   fclose(fp);
   return(0);
}
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
    const char str[] = "123456789";
    FILE *fp = fopen("tmp.txt", "w");
    size_t size = fwrite(str, strlen(str), 1, fp);
    printf("size is %d\n", size);
    fclose(fp);
    return 0;
}
# Linux 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×