linux select用法

2023-11-16

Select可以监控多个文件句柄,监控文件内容的变化,比如可读可写状态的改变,利用select可以实现非阻塞而不会让线程挂起,提高系统的运行效率。

比如可以同时 监控 键盘输入和鼠标输入,如果键盘有信号,可以去操作键盘,如果鼠标有信号,去处理鼠标事件,如果都没有信号,则可以不让线程挂起而继续向下执行。

1、 所需头文件:

#include <sys/types.h>

#include <sys/time.h>

#include <unistd.h> 

2、函数原型

int  select(int  numfds,fd_set  *readfds, fd_set  *writefds,fd_set  *exeptfds, struct  timeval *timeout) 

numfds:需要检查的号码最高的文件描述符加 1 

readfds:由 select()监视的读文件描述符集合 

writefds:由 select()监视的写文件描述符集合 

exeptfds:由 select()监视的异常处理文件描述符集合 

timeout

struct timeval { 
        long tv_sec; /* second */ 
        long tv_unsec; /* and microseconds*/ 

NULL:永远等待,直到捕捉到信号或文件描述符已准备好为止 

具体值:struct timeval 类型的指针,若等待为 timeout 时间还没有文件描符准备好,就立即返回 

0:从不等待,测试所有指定的描述符并立即返回 

函数返回值 

成功:准备好的文件描述符 

−1:出错 

3.、select 文件描述符处理函数 

FD_ZERO(fd_set *set)  清除一个文件描述符集 
FD_SET(int fd,fd_set *set)  将一个文件描述符加入文件描述符集中 
FD_CLR(int fd,fd_set *set)  将一个文件描述符从文件描述符集中清除 
FD_ISSET(int fd,fd_set *set)  测试该集中的一个给定位是否有变化 


使用步骤:

1、定义文件描述符

如:int int fds[2]; 

        然后:fds[0] = open(....),打开文件。

2、定义要监视的集合

如:fd_set inset1,inset2; 

初始化集合: FD_ZERO(&inset1);  

把要监视的文件描述符添加进集合: FD_SET(fds[0],&inset1);  可以添加多个。

3、 设置监视的时间:

0:从不等待

NULL:永远等待

定义时间结构体:

struct timeval tv; 

设置时间,如:

tv.tv_sec=2; 
      tv.tv_usec=0; 

注意当每次循环执行到select时,原来tv的值会被清零,必须重新设置


4、取出最大的那个文件

 maxfd = fds[0]>fds[1] ? fds[0] : fds[1]; 


5、设置select(maxfd+1,&inset1,&inset2,NULL,&tv)


6、如果select返回大于0

可以用FD_ISSET(fds[0],&inset1)测试是哪个个文件的状态的变化。


测试程序,监视 标准输入,然后打印出来

#include <stdio.h>
#include <errno.h>
#include <stdlib.h> 
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h> 

int main()
{
		//int fds; 
		int ret;
		char buf[100];
		int timecount;
		int maxfd;
		
		fd_set rfds;//设置监听读集合
		struct timeval tv;//设置等待时间,0不等待,NULL一直等待。
		
  
		FD_ZERO(&rfds);//清空集合
/*
*	通常,一个进程启动时,都会打开 3 个文件:标准输入、标准输出和标准出错处理。这
*  	3 个文件分别对应文件描述符为 0、1 和 2(也就是宏替换 STDIN_FILENO、STDOUT_FILENO
*  	和 STDERR_FILENO,鼓励读者使用这些宏替换)。 
*/
        FD_SET(STDIN_FILENO, &rfds);//把标准输入句柄0加入到集合中
    

		maxfd = STDIN_FILENO + 1;

		timecount = 0;
		while(1)
		{
			tv.tv_sec = 10;
			tv.tv_usec = 0;//设置等待时间
			ret = select(maxfd, &rfds, NULL, NULL, &tv);
			if(ret<0)
			{
				printf("select error, process will eixt\n");
				exit(0);
			}
			else if(FD_ISSET(STDIN_FILENO, &rfds))//测试是否有数据
			{
					fgets(buf, 100, stdin);
					if (!strncasecmp(buf, "quit", 4)) 
					{
						printf("exit test!\n");
						break;
					}
					printf("You input is %s\n",buf);
				
			}
			else
			{
			
				timecount++;
				printf("\ntime out: %d\n", timecount);
			
			}
		}
		return 0;
}

运行结果:

root@lj:/work/tmp/select/keypad# gcc select_key.c -o select
root@lj:/work/tmp/select/keypad# ./select
hello
You input is hello


time out: 1

time out: 2

time out: 3



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux select用法 的相关文章

  • 如何查明 Ubuntu 上安装了哪个版本的 GTK+?

    我需要确定 Ubuntu 上安装了哪个版本的 GTK 男人似乎不帮忙 这个建议 https stackoverflow com a 126145 会告诉您安装了哪个 2 0 的次要版本 不同的主要版本将具有不同的包名称 因为它们可以在系统上
  • git在Windows和Linux之间切换后强制刷新索引

    我有一个Windows和Linux共享的磁盘分区 格式 NTFS 它包含一个 git 存储库 约 6 7 GB 如果我只使用Windows or 只使用Linux操作 git 存储库一切正常 但是每次切换系统的时候git status命令将
  • 伊迪德信息

    重新定义问题 有什么方法可以获取所连接显示器的序列号吗 我想收集显示器的Eid信息 当我使用 logverbose 选项运行 X 时 我可以从 xorg 0 log 文件中获取它 但问题是 如果我切换显示器 拔出当前显示器 然后插入另一个显
  • 在 LINUX 上使用 Python 连接到 OLAP 多维数据集

    我知道如何在 Windows 上使用 Python 连接到 MS OLAP 多维数据集 嗯 至少有一种方法 通常我使用 win32py 包并调用 COM 对象进行连接 import win32com client connection wi
  • 为 Qt 应用程序创建 Linux 安装

    我刚刚用 Qt Creator 制作了一个很棒的程序 我对自己很满意 如何将其从台式机移至笔记本电脑 那么 最好的方法是安装程序 对吗 对于 Ubuntu 这是一个 Debian 软件包 对吗 我怎么做 有人这样做过吗 他们可以分享 QT
  • 如何在Python中独立于语言安装(linux)获取用户桌面路径

    我找到了 如何找到用户桌面的路径 的几个问题和答案 但在我看来它们都已失效 至少我找到的那些 原因是 如果用户安装的 Linux 不是英语 他或她的桌面很可能位于除 Desktop 例如 对于瑞典语 我相信它是在 Skrivbord 谁知道
  • 每个进程每个线程的时间量

    我有一个关于 Windows 和 Linux 中进程和线程的时间量子的问题 我知道操作系统通常为每个线程提供固定的时间量 我知道时间量根据前台或后台线程而变化 也可能根据进程的优先级而变化 每个进程有固定的时间量吗 例如 如果操作系统为每个
  • sleep 0 有特殊含义吗?

    我看到很多用法sleep 0在我的一个客户项目中 代码看起来像这样 while true sleep 0 end 阅读一些像这样的答案this https stackoverflow com questions 3727420 signif
  • 无需 cron 在后台发送邮件

    我想知道是否有一种方法可以运行 PHP 循环 以便在后台向订阅者发送几百封电子邮件 我的目标是格式化新闻通讯 单击发送 然后关闭浏览器或更改页面 当然 发送电子邮件的实际过程将在后台运行 不会因浏览器关闭而中断 我知道这可以通过 cron
  • 劫持系统调用

    我正在编写一个内核模块 我需要劫持 包装一些系统调用 我正在暴力破解 sys call table 地址 并使用 cr0 来禁用 启用页面保护 到目前为止一切顺利 一旦完成 我将公开整个代码 因此如果有人愿意 我可以更新这个问题 无论如何
  • 为什么 Linux 对目录使用 getdents() 而不是 read()?

    我浏览 K R C 时注意到 为了读取目录中的条目 他们使用了 while read dp gt fd char dirbuf sizeof dirbuf sizeof dirbuf code Where dirbuf是系统特定的目录结构
  • 信号处理程序有单独的堆栈吗?

    信号处理程序是否有单独的堆栈 就像每个线程都有单独的堆栈一样 这是在 Linux C 环境中 来自 Linux 手册页signal 7 http kernel org doc man pages online pages man7 sign
  • 嵌入式Linux poll()不断返回

    我有一个特别的问题 当我知道没有什么可读时 民意调查不断返回 因此设置如下 我有 2 个文件描述符 它们构成fd设置民意调查监视 一种用于引脚从高到低的变化 GPIO 另一个用于代理输入 代理输入出现问题 处理的顺序是 启动main函数 然
  • QFileDialog::getSaveFileName 和默认的 selectedFilter

    我有 getSaveFileName 和一些过滤器 我希望当用户打开 保存 对话框时选择其中之一 Qt 文档说明如下 可以通过将 selectedFilter 设置为所需的值来选择默认过滤器 我尝试以下变体 QString selFilte
  • 在Linux上编译C# + WPF以便在Windows上运行

    我有一个 C 应用程序 其中某些部分是使用 WPF 编写的 Mono 不支持 可以在 Linux 上编译这个应用程序吗 最终 该应用程序将在 Windows 上运行 但它是更大框架的一部分 并且我们的整个构建过程在 Linux 上运行 因此
  • ansible 重新启动 2.1.1.0 失败

    我一直在尝试创建一个非常简单的 Ansible 剧本 它将重新启动服务器并等待它回来 我过去在 Ansible 1 9 上有一个可以运行的 但我最近升级到 2 1 1 0 并且失败了 我正在重新启动的主机名为 idm IP 为 192 16
  • Locale.getDefault() 始终返回 en

    unix 机器上的服务器始终使用 en 作为默认区域设置 以下是区域设置输出 LANG en US LC CTYPE C LC NUMERIC C LC TIME C LC COLLATE C LC MONETARY C LC MESSAG
  • 在 Mac OS X 上构建 Linux 内核

    我正在做一个修改Linux内核的项目 我有一台桌面 Linux 机器 在上面构建内核没有问题 不过 我要去旅行 我想在途中工作 我只有一台 MacBook 当我尝试构建 Linux 内核时 它抱怨说elf h was not found 我
  • 拆分字符串以仅获取前 5 个字符

    我想去那个地点 var log src ap kernelmodule 10 001 100 但看起来我的代码必须处理 ap kernelmodule 10 002 100 ap kernelmodule 10 003 101 等 我想使用
  • 何时使用 pthread 条件变量?

    线程问题 看来 只有在其他线程调用 pthread cond notify 之前调用 pthread cond wait 时 条件变量才起作用 如果在等待之前发生通知 那么等待将被卡住 我的问题是 什么时候应该使用条件变量 调度程序可以抢占

随机推荐