fd

基于swoole+Redis的消息实时推送通知

泄露秘密 提交于 2019-12-14 11:01:02
swoole+Redis将实时数据的推送 一 实现功能 设计师订单如果设计师未抢单,超时(5分钟)设计订单时时给设计师派送, 设计师公众号中收到派单信息 设计发布者收到派单成功信息 环境 centos6.10 redis-4.0.2 swoole-src-4.4.12 php-7.1.5 MYsyql5.7 在centos6默认是gcc-4.7,安装swoole的时候需要升级到gcc-4.8 二 实现流程 1.开启swoole server端监听 2.开启swoole client连接执行定时执行 3.使用swoole task 异步执行推送逻辑 开始监听 服务端窗口 # php71 pushServer.php client连接执行开始任务 客户端窗口 # php71 pushClient.php start 默认start开启5个client tcp链接,每个链接开启一个1s定时器 开启后服务端窗口的变化 [root@111111 swoole_server]# php71 pushServer.php Client-1: 连接成功 reactor-7 Client-1 接受数据: data=start Client-1: 连接结束 Client-2: 连接成功 reactor-0 Client-2 接受数据: data=start Client-3: 连接成功 Client

Epoll模型详解

旧时模样 提交于 2019-12-13 10:37:50
1. 内核中提高I/O性能的新方法epoll epoll是什么?按照man手册的说法:是为处理大批量句柄而作了改进的poll。要使用epoll只需要这三个系统调 用:epoll_create(2), epoll_ctl(2), epoll_wait(2)。当然,这不是2.6内核才有的,它是在 2.5.44内核中被引进的(epoll(4) is a new API introduced in Linux kernel 2.5.44) Linux2.6 内核epoll介绍: 先介绍2本书《The Linux Networking Architecture--Design and Implementation of Network Protocols in the Linux Kernel》,以2.4内核讲解Linux TCP/IP实现,相当不错.作为一个现实世界中的实现,很多时候你必须作很多权衡,这时候参考一个久经考验的系统更有实际意义。举个例子linux内 核中sk_buff结构为了追求速度和安全,牺牲了部分内存,所以在发送TCP包的时候,无论应用层数据多大,sk_buff最小也有272的字节.其实对于socket应用层程序来说,另外一本书《UNIX Network Programming Volume 1》意义更大一点.2003年的时候,这本书出了最新的第3版本

linux文件删除正在读写的文件

老子叫甜甜 提交于 2019-12-12 19:19:26
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 背景知识 多进程环境下,打开同一个文件,进行读写操作过程中,如果其中一个进程删除这个文件,那么,另外正在读写这个文件会发生什么呢? 因为文件被删除了,正在读写的进程发生异常? 正在读写的进程仍然正常读写,好像没有发现发生了什么? Linux 是通过 link 的数量来控制文件删除,只有当一个文件不存在任何 link 的时候,这个文件才会被删除。 每个文件都有 2 个 link 计数器 —— i_count 和 i_nlink。i_count 的意义是当前使用者的数量,i_nlink 的意义是介质连接的数量;或者可以理解为 i_count 是内存引用计数器,i_nlink 是硬盘引用计数器。再换句话说,当文件被某个进程引用时,i_count 就会增加;当创建文件的硬连接的时候,i_nlink 就会增加。 对于 rm 而言,就是减少 i_nlink。这里就出现一个问题,如果一个文件正在被某个进程调用,而用户却执行 rm 操作把文件删除了,会出现什么结果呢? 当用户执行 rm 操作后,ls 或者其他文件管理命令不再能够找到这个文件,但是进程却依然在继续正常执行,依然能够从文件中正确的读取内容。这是因为, rm 操作只是将 i_nlink 置为 0 了;由于文件被进程引用的缘故,i_count 不为 0

多个线程如何操作同一个epoll fd

陌路散爱 提交于 2019-12-12 14:05:33
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 自己以前做一个接口服务器时候,这种场景下我的设计是多个线程操作同一个epoll fd。彼时,我的理由是epoll的系列函数是线程安全的。 当然有人不理解为什么会有多个线程操作同一个epoll fd的情形,这里稍微铺陈一下接口服务器的场景。epoll fd有线程1维护,监听服务端端口的socket的accept出来的acceptor(即新的socket fd)也放在这个epoll fd中。当收到客户端链接请求时候,线程2从连接池connector pool中挑选出来一个connector,connector的作用是转发请求,此时connector会把acceptor缓存起来。如果connector收到回复后,connector会通过acceptor向客户端返回一些数据后,线程2此时需要把acceptor在add进epoll fd中。 以前我以为epoll fd是多线程安全的,我就直接通过epoll_ctl(epoll fd,acceptor,add) 把acceptor放进epoll fd中。 现在再回首看看,自己是想当然的这样操作了,没有任何依据。孟子曰,“行有不得,反求诸己”。既然自己无法解开困惑,那就求助伟大的man了。通过“man epoll_wait”后,得到这么一句话: NOTES While one

linux epoll使用详解

时间秒杀一切 提交于 2019-12-12 13:48:38
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> Linux2.6内核中epoll用法详解 引言 epoll是linux2.6内核中才有的机制,其他版本内核中是没有的,是Linux2.6内核引入的多路复用IO的一种方式,用于提高网络IO 性能的方法。在linux网络编程中,很长一段时间都是采用select来实现多事件触发处理的。Select存在如下几个方面的问题:一是每次调用时要 重复地从用户态读入参数,二是每次调用时要重复地扫描文件描述符,三是每次在调用开始时,要把当前进程放入各个文件描述符的等待队列。在调用结束后,又把 进程从各个等待队列中删除。Select采用轮询的方式来处理事件触发,当随着监听socket的文件描述符fd的数量增加时,轮询的时间也就越长,造成 效率低下。而且linux/posix_types.h中有#define __FD_SETSIZE 1024(也有说2048的)的定义,也就是说linux select能监听的最大fd数目是1024个,虽然能通过内核修改此参数,但这是治标不治本。 epoll的出现可以有效的解决select效率低下的问题,epoll把参数拷贝到内核态,在每次轮询时不会重复拷贝。epoll有ET和LT两种工 作模式,ET是高速模式只能以非阻塞方式进行,LT相当于快速的select,可以才有阻塞和非阻塞两种方式

man-翻译和epoll相关的内容,部分

蹲街弑〆低调 提交于 2019-12-12 13:48:23
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 1. int epoll_create(int size); epoll_create 新建了一个epoll的实例,请求内核分配一块存储事件结构的空间,size不是后台存储的最大尺寸,只是初始化时告诉内核应该分配多大的内部空间。 epoll_create 返回了一个对新的epoll实例引用的文件描述符。这个文件描述符在所有随后的epoll接口的调用中都会被用到。当不需要的时候,由epoll_create返回的文件描述符,需要用close()函数关闭。当所有对本文件应用的文件描述符都被关闭时,内核将把这个epoll实例破坏掉,并释放所分配的资源以实现再利用。 2 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) 这个系统调用控制了一个被文件描述符epfd所引用的epoll实例。它在目标文件描述符fd上请求相关的操作op。 有效的op参数如下: EPOLL_CTL_ADD 在文件描述符epfd所引用的epoll实例里注册目标文件描述符fd并把event和fd指向的文件联系起来。 EPOLL_CTL_MOD 修改和目标文件描述符fd联系起来的event。 EPOLL_CTL_DEL

网络编程12 select多路复用

最后都变了- 提交于 2019-12-12 12:37:14
int select ( int maxfd , fd_set * readset , fd_set * writeset , fd_set * exceptset , const struct timeval * timeout ) ; 返回:若有就绪描述符则为其数目,若超时则为 0 ,若出错则为 - 1 maxfd 表示的是待测试的描述符基数,它的值是待测试的最大描述符加 1。 void FD_ZERO ( fd_set * fdset ) ;        void FD_SET ( int fd , fd_set * fdset ) ;    void FD_CLR ( int fd , fd_set * fdset ) ;     int FD_ISSET ( int fd , fd_set * fdset ) ; struct timeval { long tv_sec ; /* seconds */ long tv_usec ; /* microseconds */ } ; 1、将timeval置为空,表示如果没有IO事件发生就将一直等待下去 2、表示一段固定的时间后,select从阻塞调用中返回 3、将tv_sec和tv_usec都置为0,表示不等待,立即返回 来源: CSDN 作者: track_down 链接: https://blog.csdn.net/qq

Redis 命令执行过程(上)

泄露秘密 提交于 2019-12-11 19:07:12
今天我们来了解一下 Redis 命令执行的过程。在之前的文章中 《当 Redis 发生高延迟时,到底发生了什么》 我们曾简单的描述了一条命令的执行过程,本篇文章展示深入说明一下,加深读者对 Redis 的了解。 如下图所示,一条命令执行完成并且返回数据一共涉及三部分,第一步是建立连接阶段,响应了socket的建立,并且创建了client对象;第二步是处理阶段,从socket读取数据到输入缓冲区,然后解析并获得命令,执行命令并将返回值存储到输出缓冲区中;第三步是数据返回阶段,将返回值从输出缓冲区写到socket中,返回给客户端,最后关闭client。 这三个阶段之间是通过事件机制串联了,在 Redis 启动阶段首先要注册socket连接建立事件处理器: 当客户端发来建立socket的连接的请求时,对应的处理器方法会被执行,建立连接阶段的相关处理就会进行,然后注册socket读取事件处理器 当客户端发来命令时,读取事件处理器方法会被执行,对应处理阶段的相关逻辑都会被执行,然后注册socket写事件处理器 当写事件处理器被执行时,就是将返回值写回到socket中。 接下来,我们分别来看一下各个步骤的具体原理和代码实现。 启动时监听socket Redis 服务器启动时,会调用 initServer 方法,首先会建立 Redis 自己的事件机制 eventLoop

文件I/O编程 (fcntl)

好久不见. 提交于 2019-12-11 11:24:51
Fcntl函数语法要点 所需头文件:#include #include #include 函数原型:int fcntl(int fd,cmd,struct flock *lock) 函数传入值: fd:文件描述符 Cmd:F_DUPFD:复制文件描述符 F_GETFD:获得fd的close-on-exec标志,若标志未设置,则文件经过exec函数之后仍保持打开状态。 F_SETFD:设置close-on-exec标志,该标志以参数arg的FD_CLOEXEC位决定。 F_GETFL:得到open设置的标志 F_SETFL:改变open设置的标志 F_GETFK:根据lock描述,决定是否上文件锁 F_SETFK:设置lock描述的文件锁 F_SETLKW:这是F_SETLK的阻塞版本(命令名中的W表示等待(wait))。如果存在其它锁,则调用进程睡眠;如果捕捉到信号则睡眠中断 F_GETOWN:检索将收到SIGIO和SIGURG信号的进程号或进程组号 F_SETOWN:设置进程号或进程组号 Lock:结构为flock,设置记录锁的具体状态 函数返回值:成功:0 -1:出错 Lock的结构如下所示: Struct flock{ Short l_type; Off_t l_start; Short l_whence; Off_t l_len; Pid_t l_pid; }

android 启动流程 相关

删除回忆录丶 提交于 2019-12-11 05:03:10
Android原生流程 Init进程 主要流程及分支梳理 ueventd_main() watchdogd_main() 主要流程 a) 公共部分 增加PATH 环境变量 初始化内核日志,打开/dev/kmsg,此时logcat还未初始化,使用内核的log系统 设置selinux b) First_stage Mount 和mkdir 例如/dev /proc /sys 在当前是内核态的状态下设置selinux。是否enforceing(开启)或关闭,取决于配置,若编译时允许内核指定,那么从androidboot.selinux 的取值决定开关,否则默认打开,编译配置ALLOW_PERMISSIVE_SELINUX为false的话,那么需要开启selinux到enforceing状态(在system/core/init/Android.mk中) Execv() 重新执行当前 init进程的镜像,并带入 –-second-stage 参数重新执行main()进入第二阶段 c) Second_stage property_init() 初始化property_server,读/property_contexts文件按照链表方式构造到内存分别存为prefix 和 context,建立/dev/__propertes__/* (*为context名称)