美文网首页
标准io和文件io,套接字高级io

标准io和文件io,套接字高级io

作者: m风满楼 | 来源:发表于2018-09-29 19:56 被阅读0次

概念

  • 文件I/O称之为不带缓存的IO(unbuffered I/O)。不带缓存指的是每个read,write都调用内核中的一个系统调用。也就是一般所说的低级I/O——操作系统提供的基本IO服务,与os绑定,特定于linix或unix平台。但是这个不带缓存表示用户不缓存,不代表操作系统没有缓存。
  • 标准io是ANSI C建立的一个标准I/O模型,是一个标准函数包和stdio.h头文件中的定义,具有一定的可移植性。标准I/O库处理很多细节。例如缓存分配,以优化长度执行I/O等。标准的I/O提供了三种类型的缓存。
    • 全缓存:当填满标准I/O缓存后才进行实际的I/O操作。
    • 行缓存:当输入或输出中遇到新行符时,标准I/O库执行I/O操作。
    • 不缓存:stderr就是了。

区别

  • 文件I/O 又称为低级磁盘I/O,遵循POSIX相关标准。
  • 标准I/O被称为高级磁盘I/O,遵循ANSI C相关标准
  • 通过文件I/O读写文件时,每次操作都会执行相关系统调用。这样处理的好处是直接读写实际文件,坏处是频繁的系统调用会增加系统开销,标准I/O可以看成是在文件I/O的基础上封装了缓冲机制。先读写缓冲区,必要时再访问实际文件,从而减少了系统调用的次数
  • 文件I/O中用文件描述符表现一个打开的文件,可以访问不同类型的文件如普通文件、设备文件和管道文件等。而标准I/O中用FILE(流)表示一个打开的文件,通常只用来访问普通文件。
API区别:

文件io

#include <fcntl.h>
#include <unistd.h>
int open(const char *pathname, int oflag, ... mode_t mode);
#成功返回文件描述符, 失败返回-1 
int close(int filedes);
#成功返回0, 失败返回-1
off_t lseek(int filedes, off_t offset, int whence);
#成功返回新的文件偏移量,出错返回-1 
ssize_t read(int filedes, void *buf, size_t nbytes);
#成功则返回读取到的字节数,若已到文件的结尾返回0,出错返回-1 
ssize_t write(int filedes, void *buf, size_t nbytes);
#成功则返回写入的字节数,出错返回-1 

标准io

  • 除非引用终端设别,否则系统默认流打开是全缓冲的。
打开 
#include <stdio.h>
#fopen 打开一个指定的文件
FILE *fopen(const char *restrict pathname, const char *restrict type);
#freopen 在一个指定的流上打开一个文件,比如在标准输出流上打开某文件
FILE *freopen(const char *restrict pathname, const char *restrict type, FILE *restrict fp);
#dopen 打开指定的文件描述符代表的文件。常用于读取管道或者其他特殊类型的文件,因为这些文件不能直接用fopen打开。
FILE *dopen(int filedes, const char *type);
# 成功返回FILE类型指针,出错返回NULL 
# type 参数指定操作类型,入读写,追加等等。

关闭
#include <stdio.h>
int flose(FILE *fp);
# 成功返回0,出错返回EOF 
每次一个字符的io
#include <stdio.h>

每次一个字符的IO流
输入 
int getc(FILE *fp);
int fgetc(FILE *fp);
int getchar(void);
#上面三个函数的返回值为int,因为EOF常实现为-1,返回int就能与之比较 

判断出错或者结束 
int ferror(FILE *fp);
int feof(FILE *fp);
void clearerr(FILE *fp); 
#清除error或者eof标志 

输出
int putc(int c, FILE *fp);
int fputc(int c, FILE *fp);
int putchar(int c);

每次一行的IO流
#include <stdio.h>
#输入
char *fgets(char *restrict buf, int n, FILE *restrict fp);
char *gets(char *buf);
#gets由于没有指定缓冲区,所以有可能造成缓冲区溢出,要小心 

#输出
int fputs(char *restrict buf, FILE *restrict fp);
int puts(const char *buf);

#格式化输出IO流
printf 输出到标准输出
fprintf 输出到指定流
sprintf 输出到指定数组
snprintf 输出到指定数组并在数组的尾端自动添加一个null字节

#格式化输入IO流
scanf 从标准输入获取
fscanf 从指定流获取
sscanf 从指定数组获取

网络高级io

#include <sys/socket.h>
ssize_t recv(int sockfd, void * buff, size_t nbytes, int flags);
    success return recv-byte-count, error return -1
ssize_t send(int sockfd, const void * buff, size_t nbytes, int flags);
    success return send-byte-count, error return -1
    flags:
        MSG_DONTROUTE, MSG_DONTWAIT, MSG_OOB, MSG_PEEK, MSG_WAITALL
 
/* if system support MSG_WAITALL */
#define readn(fd, ptr, n) recv(fd, ptr, n, MSG_WAITALL)
 
#include <sys/uio.h>
ssize_t readv(int fileds, const struct iovec * iov, int iovcnt);
    success return total-read-byte-count, error return -1
ssize_t writev(int fileds, const struct iovec * iov, int iovcnt);
    success return total-write-byte-count, error return -1
    struct iovec {
        void  * iov_base; /* starting address of buffer */
        size_t  iov_len;  /* size of buffer */
    };
 
#include <sys/socket.h>
ssize_t recvmsg(int sockfd, struct msghdr * msg, int flags);
    success return recv-byte-count, error return -1
ssize_t sendmsg(int sockfd, struct msghdr * msg, int flags);
    success return send-byte-count, error return -1
    struct msghdr {
        void         * msg_name;        /* protocol address */
        socklen_t      msg_namelen;     /* size of protocol address (val-ret)*/
        struct iovec * msg_iov;         /* scatter/gather array */
        int            msg_iovlen;      /* element-count in msg_iov */
        void         * msg_control;     /* ancillary data (cmsghdr struct) */
        socklen_t      msg_controllen;  /* length of ancillary data */
        int            msg_flags;       /* flags returned by recvmsg() */
        ...
    };
    flags:
        MSG_DONTROUTE, MSG_DONTWAIT, MSG_OOB, MSG_PEEK, MSG_WAITALL
    msg_flags:
        MSG_DONTROUTE, MSG_DONTWAIT, MSG_OOB, MSG_PEEK, MSG_WAITALL
        MSG_BCAST, MSG_MCAST, MSG_TRUNC, MSG_CTRUNC, MSG_EOR, MSG_NOTIFICATION
    struct cmsghdr {
        socklen_t  cmsg_len;   /* length in bytes, including this structure */
        int        cmsg_level; /* originating protocol */
        int        cmsg_type;  /* protocol-specific type */
        /* followed by unsigned char cmsg_data[] */
    };
 
#include <sys/socket.h>
#include <sys/param.h> /* for ALIGN macro on many implementations */
struct cmsghdr * CMSG_FIRSTHDR(struct msghdr * mhdrptr);
struct cmsghdr * CMSG_NXTHDR(struct msghdr * mhdrptr, 
                             struct cmsghdr * cmsgptr);
unsigned char * CMSG_DATA(struct cmsghdr * cmsgptr);
 
unsigned int CMSG_LENGTH(unsigned int length);
unsigned int CMSG_SPACE(unsigned int length);
 
usage:
    struct msghdr    msg;
    struct cmsghdr * cmsgptr;
    /* fill in msg structure */
    /* call recvmsg() */
    for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; 
         cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
        if (cmsgptr->cmsg_level == ... && 
            cmsgptr->cmsg_type == ...) {
            u_char * ptr = CMSG_DATA(cmsgptr);
            /* process data */
        }
    }
 
/dev/poll - interface:
#include <sys/devpoll.h>
struct dvpoll {
    struct pollfd * dp_fds;
    int             dp_nfds;
    int             dp_timeout;
};
 
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
int kqueue(void);
int kevent(int kq, const struct kevent * changelist, int nchanges, 
           struct kevent * eventlist, int nevents, 
           const struct timespec * timeout);
void EV_SET(struct kevent * kev, uintptr_t ident, short filter, 
            u_short flags, u_int fflags, intptr_t data, void * udata);
    struct kevent {
        uintptr_t  ident;
        short      filter;
        u_short    flags;
        u_int      fflags;
        intptr_t   data;
        void     * udata;
    };
    flags:
        EV_ADD,     EV_CLEAR,  EV_DELETE,  (value)
        EV_DISABLE, EV_ENABLE, EV_ONESHOT, (value)
        EV_EOF,     EV_ERROR               (result)
    filter:
        EVFILT_AIO, EVFILT_PROC, EVFILT_READ, EVFILT_SIGNAL, 
        EVFILT_TIMER, EVFILT_VNODE, EVFILT_WRITE



参考连接:
上下文切换详解
Unix/Linux中的read和write函数

相关文章

  • 标准io和文件io,套接字高级io

    概念 文件I/O称之为不带缓存的IO(unbuffered I/O)。不带缓存指的是每个read,write都调用...

  • 了不起的NodeJS(一)

    Node 异步IO、事件循环、非阻塞IO、回调 异步IO调用示意图IO被为文件读写,而文件被抽象为磁盘、网络套接字...

  • Linux 文件IO 和 标准IO

    [TOC] Linux 文件IO 和 标准IO Linux 文件IO Linux中做文件IO最常用到的5个函数是:...

  • Linux - 网络IO

    IO事件 标准输入文件描述符可以读 已连接套接字准备好可以写 如果一个IO事件等待超过10秒,发生超时 阻塞 我们...

  • 高级IO

    本篇文章主要涉及的内容有阻塞和非阻塞IO,同步异步IO,还有网络套接字IO,包括select,poll,epoll...

  • IO模型

    描述 本文摘自UNIX网络编程卷1:套接字联网API,描述了UNIX中五种IO模型。阻塞IO、非阻塞IO、IO复用...

  • c--文件io和标准io

    出错处理 内核通过全局变量errno来指明错误的类型,每个程序都可以访问这个变量。当系统调用出错时,会把全局变量e...

  • 11.标准IO库

    标准IO和文件IO有什么区别 看起来使用时都是函数,但是:标准IO是C库函数,而文件IO是linux系统的API ...

  • Linux系统编程(open, read, write)

    大纲 一、系统调用的文件IO 系统的文件IO和C标准的IO的不同 图解大纲C标准的在用户空间,系统调用的在内核空间...

  • linux高级环境编程-标准IO

    标准IO也是带缓存的IO,它们的操作是围绕流进行,而之前的不带缓存IO操作是围绕文件描述符的,标准IO还是基于文件...

网友评论

      本文标题:标准io和文件io,套接字高级io

      本文链接:https://www.haomeiwen.com/subject/tguboftx.html