linux学习笔记_9.TCP高级应用

TCP高级应用

文件I/O方式

阻塞式

应用程序对驱动文件在进行IO操作的时候,一般分为阻塞和非阻塞两种模式,针对阻塞IO模式来说,如果APP不能操作对应的文件,那么对文件的访问进程就会被挂起来,一直等到可以获取到设备资源后才能执行。Linux驱动程序中,通过一个叫做等待队列(wait queue)的机制来唤醒被的阻塞操作。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PBZhZNXj-1665229997899)(C:\Users\nice\AppData\Roaming\Typora\typora-user-images\image-20221005151434103.png)]

非阻塞式

非阻塞IO是不会将文件操作进程挂起来进入休眠状态,而是不停的轮训等待直到资源可以被使用或者放弃。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MwVuJHIS-1665229997901)(C:\Users\nice\AppData\Roaming\Typora\typora-user-images\image-20221005151459061.png)]

多路复用I/O

依旧是阻塞方式等待文件IO,但可以同时等待多个文件描述符。

让一个进程同时监视多个socket,一旦有socket数据准备完成,便可以直接进行数据拷贝过程。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NEMHWOFy-1665229997901)(C:\Users\nice\AppData\Roaming\Typora\typora-user-images\image-20221005151913911.png)]

select
int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);

/*maxfdp——传入参数,集合中所有文件描述符的范围,即最大文件描述符值+1
 readfds——传入传出参数,select调用时传入要监听的可读文件描述符集合,select返回时传出发生可读事件的文件描述符集合
 writefds——传入传出参数,select调用时传入要监听的可写文件描述符集合,select返回时传出发生可写事件的文件描述符集合
 errorfds——传出参数,select返回时传出发生事件(包括可读和可写)中异常事件的文件描述符集合
 timeout——传入参数,设置select阻塞的时间。若设置为NULL,则select一直阻塞直到有事件发生;
                                      若设置为0,则select为非阻塞模式,执行后立即返回;
                                      若设置为一个大于0的数,即select的阻塞时间,若阻塞时间内有事件发生就返回,否则时间到了立即返回*/


//fd_set是自定义的一个数据结构,可看作一个集合,存放可读、可写或异常事件的文件描述符。
//fd_set集合通常有以下四个宏来操作:
void FD_ZERO(fd_set *fdset);  //清空fdset中所有文件描述符
void FD_SET(int fd,fd_set *fdset);  //添加文件描述符fd到集合fdset中
void FD_CLR(int fd,fd_set *fdset); //将文件描述符fd从集合fdset中去除
int FD_ISSET(int fd,fd_set *fdset);  //判断文件描述符fd是否在集合fdset中

struct timeval
{
    long tv_sec;
    long tv_usec;
};
pselect
int pselect(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timespec *timeout, const sigset_t *sigmask);

//pselect 使用 timespec 结构,而不使用 timeval 结构
struct timespec
{
    time_t tv_sec; //秒
    long    tv_nsec; //纳秒
}; //timespec的成员 tv_nsec 指定纳秒数,而 timeval 的该成员 tv_usec 指定微秒数。

//第6个参数:一个指向信号掩码的指针。该参数允许程序先禁止递交某些信号,再测试由这些当前被禁止的信号处理函数设置的全局变量,然后调用 pselect,告诉它重新设置信号掩码。
poll
int poll(struct poll *fds, unsigned int nfds, int timeout);
struct pollfd{
  int fd;
  short events;
  short revents;
};
//poll使用一个pollfd的指针实现。pollfd结构包含了要监视的event和发生的event,不在使用select参数传值的方式。同时pollfd并没有最大数量的限制(但数量过大性能也会下降)。和select一样,poll返回后,需要轮询pollfd来或许就绪的描述符。

poll()函数监视在fds数组指明的一组文件描述符上发生的动作,当满足条件或超时的时候会退出。

fds:指向结构pollfd数组的指针,监视的文件描述符和条件放在里面。
nfds:比监视的最大描述符的值大1
timeout:超时时间,单位毫秒,负值表示永远等待。
pollfd结构中events和revents的值及含义如下:

  • POLLIN 普通或优先级带数据可读
  • POLLRDNORM 普通数据可读
  • POLLRDBAND 优先级带数据可读
  • POLLPRI 高优先级数据可读
  • POLLOUT 普通数据可写
  • POLLWRNORM 普通数据可写
  • POLLWRBAND 优先级带数据可写
  • POLLERR 发生错误
  • POLLHUP 发生挂起
  • POLLNVAL 描述字不是一个打开的文件
ppoll
int ppoll(pollfd* fds,nfds_t nfds,
		  const timespec* timeout,const sigset_t* sigmask);
//与poll()区别:
// 超时时间采用了纳米级的变量
// 可以在ppoll函数的处理过程中挂接临时的信号掩码。
信号驱动I/O

异步处理。

信号驱动式I/O是指进程预先告知内核,使得当某个描述符上发生某事时,内核使用信号通知相关进程。

异步I/O是进程执行I/O系统调用(读或写)告知内核启动某个I/O操作,内核启动I/O操作后立刻返回到进程,进程在I/O操作发生期间继续执行,当操作完成或遭遇错误时,内核以进程在I/O系统调用中指定的某种方式通知进程,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-koPSpgXM-1665229997902)(C:\Users\nice\AppData\Roaming\Typora\typora-user-images\image-20221005153059834.png)]

socket文件描述符属性

get/setsockopt
int getsockopt(int socket, int level, int option_name,
            void *restrict option_value, socklen_t *restrict option_len);
int setsockopt( int socket, int level, int option_name,const void *option_value, size_t ,ption_len);

功能: 获取一个套接字的选项
参数:

  • socket:文件描述符

  • level:协议层次

    • ​ SOL_SOCKET 套接字层次
    • ​ IPPROTO_IP ip层次
    • ​ IPPROTO_TCP TCP层次
  • option_name:选项的名称(套接字层次)

    • SO_BROADCAST     允许发送广播数据            int

    • SO_DEBUG        允许调试                int

    • SO_DONTROUTE     不查找路由               int

    • SO_ERROR        获得套接字错误             int

    • SO_KEEPALIVE      保持连接                int

    • SO_LINGER        延迟关闭连接              struct linger

    • SO_OOBINLINE      带外数据放入正常数据流         int

    • SO_RCVBUF        接收缓冲区大小             int

    • SO_SNDBUF        发送缓冲区大小             int

    • SO_RCVLOWAT      接收缓冲区下限             int

    • SO_SNDLOWAT      发送缓冲区下限             int

    • SO_RCVTIMEO       接收超时                struct timeval

    • SO_SNDTIMEO       发送超时                struct timeval

    • SO_REUSERADDR    允许重用本地地址和端口         int

    • SO_TYPE         获得套接字类型             int

    • SO_BSDCOMPAT     与BSD系统兼容              int

    • IP_HDRINCL       在数据包中包含IP首部          int

    • IP_OPTINOS       IP首部选项               int

    • IP_TOS         服务类型

    • IP_TTL         生存时间                int

    • TCP_MAXSEG       TCP最大数据段的大小           int

    • TCP_NODELAY       不使用Nagle算法             int

  • option_value:获取/设置的选项的值

  • option_len:value的长度

返回值
成功:0
失败:-1

fcntl

fcntl系统调用可以用来对已打开的文件描述符进行各种控制操作以改变已打开文件的的各种属性

int fcntl(int filedes,int cmd, ... /*int arg*/);        
 //返回值:成功依赖cmd的值,失败返回-1;

四个命令有特有的返回值:

F_DUPFD:返回一个新的文件描述符;

F_GETFD、F_GETFL:返回相应的标志;

F_GETOWN: 返回一个正的或者负的进程组ID;

fcntl函数有5种功能:

  1. 复制一个现有的描述符(cmd=F_DUPFD);
  2. 获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD);
  3. 获得/设置文件状态标记(cmd=F_GETFL或F_SETFL);
  4. 获得/设置异步I/O所有权(cmd=F_GETOWN或F_SETOWN);
  5. 获得/设置记录锁(cmd=F_GETLK , F_SETLK或F_SETLKW);
  • F_DUPFD:复制文件描述符filedes。新文件描述符作为函数的返回。类似于pud,pud2;
  • F_GETFD:对应于filedes的文件描述符标志作为函数的值返回。当前只定义了一个文件描述符标志FD_CLOEXEC。
  • F_SETFD:对于filedes设置文件描述符标志。新标志值按第三个参数(取为整型值)设置。
  • F_GETFL:对应于文件状态标志作为函数值返回。
    • O_RDONLY 只读打开
    • O_WRONLY 只写打开
    • O_RDWR 为读、写打开
    • O_APPEND 每次写时追加
    • O_NONBLOCK 非阻塞模式
    • O_SYNC 等待写完成(数据和属性)
    • O_DSYNC 等待写完成(数据)
    • O_RSYNC 同步读、写
    • O_FSYNC 等待写完成(进FreeBSD和Mac OS X)
    • O_ASYNC 异步I/O(进FreeBSD和Mac OS X)
  • F_SETFL:将文件状态标志设置成为第三个参数的值(取整形值)。
  • F_GETOWN:取当前接受SIGIO和SIGURG信号的进程ID和进程组ID.正的arg指定一个进程ID,负的arg表示等于arg绝对值的一个进程中ID。
ioctl

ioctl是设备驱动程序中对设备的I/O通道进行管理的函数 。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等

int ioctl(int fd, int cmd, ...) ;

参数: fd是用户程序打开设备时使用open函数返回的文件标示符,cmd是用户程序对设备的控制命令,后面是一些补充参数,一般最多一个,这个参数的有无和cmd的意义相关。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值