linux系统和网络(三):IO,信号,信号量,线程

        本文主要探讨linux的IO,信号,信号量,线程相关知识,详细知识可参考本博客其他文章。

信号(可参考本博客其他文章)
        信号是内容受限的异步通信机制,硬件异常后统内核发出信号

         alarm产生SIGALARM信号,读端关闭后管道write产生SIGPIPE信号

常见信号
SIGINT             2         Ctrl+C(前台进程组中每个进程)
SIGABRT            6         异常终止
SIGPOLL   SIGIO    8         异步IO
SIGKILL            9         杀死进程
SIGSEGV            11        无效存储访问信号
SIGPIPE            13        管道,socket
SIGALARM           14        alarm
SIGTERM            15        kill命令默认
SIGCHLD            17        子进程终止(父进程接收信号)
SIGUSR1            10        自定义信号
SIGUSR2            12        自定义信号

        信号处理

typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

默认处理SIG_DFL
忽略处理SIG_IGN
捕获处理handler
返回出错为SIG_ERR
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
struct sigaction {
               void     (*sa_handler)(int);
               void     (*sa_sigaction)(int, siginfo_t *, void *);
               sigset_t   sa_mask;
               int        sa_flags;
               void     (*sa_restorer)(void);
           };

        sigaction可设置新捕获函数和获取旧的捕获函数,signal须在新捕获函数中获取旧捕获函数


        alarm和pause

                alarm内核提供闹钟的API

unsigned int alarm(unsigned int seconds);
int pause(void);

                内核挂起,进程暂停运行,交出CPU给其他进程(阻塞住),需被信号唤醒

信号量(可参考本博客其他文章)

sem_t sem; 
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_destroy(sem_t *sem);
int sem_wait(sem_t *sem);
int sem_post(sem_t *sem);
sem:信号量,pshared:0线程间非0用于进程,value:信号量初值

IO
        阻塞IO:wait、pause、sleep、read、write等
        非阻塞IO访问:添加O_NONBLOCK模式(fd调用fcntl)
        select和poll(多路复用IO):外部阻塞式,内部非阻塞式自动轮询多路阻塞式IO

int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd {
               int   fd;         /* 文件描述符*/
               short events;     /* 监控事件 */
               short revents;    /* 监控事件中满足条件的返回事件*/
           };

POLLIN普通或带外优先数据可读,即POLLRDNORM | POLLRDBAND
POLLRDNORM 数据可读
POLLRDBAND 优先级带数据可读
POLLPRI 高优先级可读数据
POLLOUT普通或带外数据可写
POLLWRNORM 数据可写
POLLWRBAND 优先级带数据可写
POLLERR 发生错误
POLLHUP 发生挂起
POLLNVAL 描述字不是一个打开的文件

nfds:监控文件描述符个数

timeout:等待(ms),-1阻塞等,0:不阻塞进程,>0等待指定毫秒数
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);

nfds:监控文件描述符个数

struct timeval {
               long    tv_sec;         /* seconds */
               long    tv_usec;        /* microseconds */
           };

       and

           struct timespec {
               long    tv_sec;         /* seconds */
               long    tv_nsec;        /* nanoseconds */
           };

FD_ZERO(fd_set* fdset): 将fd_set位初始化为0
FD_SET(int fd, fd_set* fdset):注册文件描述符fd信息
FD_CLR(int fd, fd_set* fdset):清除文件描述符fd信息
FD_ISSET(int fd, fd_set* fdset):fd_set包含文件描述符fd信息返回真

        异步IO(操作系统中断)
        存储映射IO(mmap):共享内存,提高效率(LCD显示和IPC间共享内存)

线程(可参考本博客其他文章)
        进程:CPU时分复用,实现多任务系统需求,进程间切换开销大,通信效率低
        线程间通信效率高且可多任务

        线程函数
                线程创建,退出,回收,分离,id

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
void pthread_exit(void *retval);
int pthread_join(pthread_t thread, void **retval);
int pthread_detach(pthread_t thread);
pthread_t pthread_self(void);

线程退出后,主线程pthread_join回收子线程,pthread_detach是线程分离,子线程自回收

 
                取消线程

int pthread_cancel(pthread_t thread);

线程取消状态
int pthread_setcancelstate(int state, int *oldstate);
PTHREAD_CANCEL_ENABLE:线程可取消(默认值)
PTHREAD_CANCEL_DISABLE:线程不可取消,取消请求挂起至线程状态为 PTHREAD_CANCEL_ENABLE

线程取消性类型
int pthread_setcanceltype(int type, int *oldtype);
PTHREAD_CANCEL_DEFERRED:取消请求到达,线程继续运行,取消请求挂起,直到线程到达取消点(默认)
PTHREAD_CANCEL_ASYNCHRONOUS:立即取消

线程清理函数中添加和移除清理函数
void pthread_cleanup_push(void (*routine)(void *),void *arg);
void pthread_cleanup_pop(int execute);
routine:清理函数,arg给清理函数传参
execute为0清理函数不调用且清理函数栈中最顶层函数移除,非0还清除清理该函数
线程清理函数中添加(入栈)和清理(出栈)次数相同

                互斥量(代码保护)

pthread_mutex_t mutex;
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);


                线程条件

pthread_cond_t  cond;
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct timespec *restrict abstime);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);

demo1:

              linux的sleep命令

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void func(int sig)
{

}

void my_sleep(unsigned int sec)
{
        struct sigaction act = {0};
        act.sa_handler = func;
        sigaction(SIGALRM, &act, NULL);
        alarm(sec);
        pause();
}


int main(int argc,char *argv[])
{
        if(argc != 2)
                printf("ex: ./a.out sec");
        printf("my_sleep start\n");
        my_sleep(atoi(argv[1]));
        printf("my_sleep end\n");

        return 0;
}

结果显示:  

demo2: 

        多路io(poll)监控鼠标和键盘

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>

int main(void)
{
        int fd;
        int ret;
        char buf[256];
        struct pollfd fds[2] = {0};

        fd = open("/dev/input/mouse0", O_RDONLY);
        if (fd < 0)
        {
                perror("open");
                return -1;
        }

        fds[0].fd = 0;
        fds[0].events = POLLIN;

        fds[1].fd = fd;
        fds[1].events = POLLIN;

        ret = poll(fds,2, 10000);
        if (ret < 0)
        {
                perror("poll");
                return -1;
        }
        else if (ret == 0)
        {
                printf("timeout\n");
        }
        else
        {
                if (fds[0].events == fds[0].revents)
                {
                        memset(buf, 0, sizeof(buf));
                        read(0, buf, 5);
                        printf("keyboard:%s\n", buf);
                }

                if (fds[1].events == fds[1].revents)
                {
                        memset(buf, 0, sizeof(buf));
                        read(fd, buf, 50);
                        printf("mouse:%s\n", buf);
                }
        }

        return 0;
}

结果显示:

        多路io(select)监控鼠标和键盘 

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>


int main()
{
        int fd;
        int ret;
        char buf[256];
        fd_set set;
        struct timeval tm;

        fd = open("/dev/input/mouse0", O_RDONLY);
        if (fd < 0)
        {
                perror("open:");
                return -1;
        }

        FD_ZERO(&set);
        FD_SET(fd, &set);
        FD_SET(0, &set);

        tm.tv_sec = 10;
        tm.tv_usec = 0;

        ret = select(fd+1, &set, NULL, NULL, &tm);
        if (ret < 0)
        {
                perror("select");
                return -1;
        }
        else if (ret == 0)
        {
                printf("timeout\n");
        }
        else
        {
                if (FD_ISSET(0, &set))
                {
                        memset(buf, 0, sizeof(buf));
                        read(0, buf, 5);
                        printf("keyboard:%s\n", buf);
                }

                if (FD_ISSET(fd, &set))
                {
                        memset(buf, 0, sizeof(buf));
                        read(fd, buf, 50);
                        printf("mouse:%s\n", buf);
                }
        }

        return 0;
}

结果显示:

        异步IO监控鼠标和键盘 (可配合poll.selectshi用)

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>

int mouse_fd;

void func(int sig)
{
        char buf[200] = {0};

        if (sig != SIGIO)
                return;

        read(mouse_fd, buf, 50);
        if(strlen(buf))
                printf("mouse:%s\n", buf);
}

int main()
{
        char buf[200];
        int flag = -1;

        mouse_fd = open("/dev/input/mouse0", O_RDONLY);
        if (mouse_fd < 0)
        {
                perror("open:");
                return -1;
        }

        //获取 mouse_fd
        flag = fcntl(mouse_fd, F_GETFL);
        //add O_ASYNC(异步)
        flag |= O_ASYNC;
        //重写 mouse_fd
        fcntl(mouse_fd, F_SETFL, flag);
        //设置 mouse_fd 接收SIGIO/SIGURG信号且与进程绑定
        fcntl(mouse_fd, F_SETOWN, getpid());

        signal(SIGIO, func);

        while (1)
        {
                memset(buf, 0, sizeof(buf));
                read(0, buf, 5);
                if(strlen(buf))
                        printf("keyboard:%s\n", buf);
        }

        return 0;
}

结果显示:

demo3: 

        字符输入和个数计算(线程+信号量)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

char buf[256] = {0};
sem_t sem;
unsigned int flag = 0;


void *func(void *arg)
{
        sem_wait(&sem);
        while (flag == 0)
        {
                printf("the num of string :%ld\n", strlen(buf));
                memset(buf, 0, sizeof(buf));
                sem_wait(&sem);
        }

        pthread_exit(NULL);
}


int main(void)
{
        int ret;
        pthread_t th;

        sem_init(&sem, 0, 0);

        ret = pthread_create(&th, NULL, func, NULL);
        if (ret != 0)
        {
                printf("pthread_create error\n");
                exit(-1);
        }

        printf("input string:\n");
        while (scanf("%s", buf))
        {
                if (!strncmp(buf, "end", 3))
                {
                        printf("process end\n");
                        flag = 1;
                        sem_post(&sem);
                        break;
                }

                sem_post(&sem);
        }

        ret = pthread_join(th, NULL);
        if (ret != 0)
        {
                printf("join error\n");
                exit(-1);
        }

        printf("join sucess\n");
        sem_destroy(&sem);

        return 0;
}

结果显示:

         字符输入和个数计算(线程条件)

结果显示: 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/267935.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024年起重机司机(限门式起重机)证考试题库及起重机司机(限门式起重机)试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年起重机司机(限门式起重机)证考试题库及起重机司机(限门式起重机)试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作…

基于模型驱动的可解释性全色、多光谱、高光谱融合网络

摘要 摘要:同时融合高光谱(HS)、多光谱(MS)和全色(PAN)图像为生成高分辨率HS (HRHS)图像提供了一种新的范式。在这项研究中&#xff0c;我们提出了一个可解释的模型驱动的深度网络&#xff0c;用于HS, MS和PAN图像融合&#xff0c;称为HMPNet。我们首先提出了一种新的融合模型…

编译原理--递归下降分析实验C++

一、实验项目要求 1.实验目的 根据某一文法编制调试递归下降分析程序&#xff0c;以便对任意输入的符号串进行分析。本次实验的目的主要是加深对递归下降分析法的理解。 2.实验要求 对下列文法&#xff0c;用递归下降分析法对任意输入的符号串进行分析&#xff1a; &#…

【并发编程篇】定义最大线程的方法

文章目录 &#x1f354;省流&#x1f3f3;️‍&#x1f308;前言&#x1f6f8;CPU密集型&#x1f339;代码实现 &#x1f6f8;IO密集型 &#x1f354;省流 池的最大大小如何去设置 使用CPU密集型和IO密集型这2种方法 &#x1f3f3;️‍&#x1f308;前言 上一篇文章我们讲解…

音视频的编码格式与封装格式

音视频的编码格式与封装格式是两个不同的概念&#xff0c;视频封装格式常见的有&#xff1a;mp4&#xff0c;rmvb&#xff0c;avi&#xff0c;mkv&#xff0c;mov&#xff0c;mpg&#xff0c;vob&#xff0c;3gp&#xff0c;asf&#xff0c;rmvb&#xff0c;wmv&#xff0c;div…

ARM GIC (五)gicv3架构-LPI

在gicv3中,引入了一种新的中断类型。message based interrupts,消息中断。 一、消息中断 外设,不在通过专用中断线,向gic发送中断,而是写gic的寄存器,来发送中断。 这样的一个好处是,可以减少中断线的个数。 为了支持消息中断,gicv3,增加了LPI,来支持消息中断。并且…

分布式事务TCC补偿机制

文章目录 概述工作流程优缺点优点&#xff1a;缺点&#xff1a; 总结Java 示例代码 概述 TCC&#xff08;Try-Confirm-Cancel&#xff09;补偿机制是一种事务处理模式&#xff0c;用于确保分布式系统中的操作成功完成或在失败时进行补偿。TCC将一个事务拆分为三个阶段&#xf…

vue3老项目如何引入vite

vue3老项目如何引入vite 安装 npm install vite vitejs/plugin-vue --save-dev Vite官方中文文档修改package.json文件 在 npm scripts 中使用 vite 执行文件 "scripts": {"serve": "vite","build": "vite build","pr…

Vue 封装echarts柱状图(Bar)组件

目的&#xff1a;减少重复代码&#xff0c;便于维护 显示效果 组件代码 <template><div class"ldw-data-content-box"><div class"ldw-chilren-box"><div class"title" v-if"title">{{ title }}</div>…

python使用opencv提取视频中的每一帧、最后一帧,并存储成图片

提取视频每一帧存储图片 最近在搞视频检测问题&#xff0c;在用到将视频分帧保存为图片时&#xff0c;图片可以保存&#xff0c;但是会出现(-215:Assertion failed) !_img.empty() in function cv::imwrite问题而不能正常运行&#xff0c;在检查代码、检查路径等措施均无果后&…

探索应用程序的指路明灯:Route 和 Router 入门指南(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

GEE学习笔记

掩膜 ​ 在遥感图像处理中&#xff0c;"掩膜"是指一种用于隐藏或保留图像特定部分的技术。掩膜通常是一个二进制图像&#xff0c;其中的像素值为0或1&#xff0c;分别表示遮蔽或保留。 ​ 在去除云的情境中&#xff0c;掩膜通常用于隐藏图像中被云覆盖的部分&#…

【c++】入门1

c关键字 命名空间 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称将都存在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化&#xff0c;以避免命名冲突或名字污染&#xff…

《工作、消费主义和新穷人》读书笔记

总结 全书前半段描写的是工作伦理论被推行的原因 &#xff0c;后半段探讨了福利国家和资本国家对于穷人的态度&#xff0c;最后描写了全球化下工作伦理从生产型社会过度到消费型社会的概念演变&#xff0c;和大众对于新穷人态度的转变。 启示 对于我的启示在前几章是最多的&…

SpringMVC:整合 SSM 中篇

文章目录 SpringMVC - 04整合 SSM 中篇一、优化二、总结三、说明注意&#xff1a; SpringMVC - 04 整合 SSM 中篇 一、优化 在 spring-dao.xml 中配置 dao 接口扫描&#xff0c;可以动态地实现 dao 接口注入到 Spring 容器中。 优化前&#xff1a;手动创建 SqlSessionTempl…

2022第十二届PostgreSQL中国技术大会-核心PPT资料下载

一、峰会简介 本次大会以“突破•进化•共赢 —— 安全可靠&#xff0c;共建与机遇”为主题&#xff0c;助力中国数据库基础软件可掌控、可研究、可发展、可生产&#xff0c;并推动数据库生态的繁荣与发展。大会为数据库从业者、数据库相关企业、数据库行业及整个IT产业带来崭…

软件测试5未来大发展路线,测试工程师发展偏向

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、软件测试的五大…

springCould中的consul-从小白开始【4】

目录 1.consul介绍 ❤️❤️❤️ 2.安装 ❤️❤️❤️ 3.创建8006模块 ❤️❤️❤️ 4.创建80模块❤️❤️❤️ 1.consul介绍 ❤️❤️❤️ Consul 是一种用于服务发现、配置和分布式一致性的开源软件。它由HashiCorp开发和维护&#xff0c;可用于帮助构建和管理现代化的分布…

ARM学习(24)Can的高阶认识和错误处理

笔者来聊一下CAN协议帧的认识和错误处理。 1、CAN协议帧认识 CAN 差分信号&#xff0c;是经过CAN收发器转成差分信号的&#xff0c;CAN RX和TX是逻辑电平。CAN的基础知识&#xff0c;可参考笔者这边文章&#xff1a;ARM学习&#xff08;21&#xff09;STM32 外设Can的认识与驱…

零基础快速上手HarmonyOS ArkTS开发2---ArkTS开发实践

ArkTS开发实践&#xff1a; 接着上一次零基础快速上手HarmonyOS ArkTS开发1---运行Hello World、ArkTS开发语言介绍继续&#xff0c; 在上一次对于ArkTS的基础知识进行了学习&#xff0c;依照官方的课程计划&#xff0c;还有两个具体的小案例需要来实践实践&#xff1a; 实践出…