当前位置: 首页 > news >正文

营销型网站模板徐州网站排名系统

营销型网站模板,徐州网站排名系统,网站上做镜像是什么意思,企业为什么要交税非阻塞I/O 在最前面#xff0c;我们讲过IO分成带缓冲的IO和不带缓冲的IO#xff0c;但是实际上#xff0c;这个区别并不是很大#xff0c;因为缓冲区并没有影响到实际的读写。我们知道#xff0c;系统调用实际上分成两种#xff0c;高速的系统调用和低速的系统调用#…非阻塞I/O 在最前面我们讲过IO分成带缓冲的IO和不带缓冲的IO但是实际上这个区别并不是很大因为缓冲区并没有影响到实际的读写。我们知道系统调用实际上分成两种高速的系统调用和低速的系统调用换句话说低速的调用会导致系统永久性阻塞但是需要注意的是并不是磁盘IO都是低速调用。比如open、read、write函数如果这些操作不能完成就会立刻出错返回并不会导致系统阻塞。在前面的时候我们也学到过如果在open的时刻指定O_NONBLOCK或者在一个已打开的文件描述符上调用fcntl函数附加上O_NONBLOCK参数。实际上虽然指定了参数但是在某些情况下很有可能丢失信息。在大量传输信息的时候容易出现系统调用大量失败的情况。 记录锁 在很多情况下我们需要面对多方一起操作文件的情况这就是一个典型的资源竞争冲突为了保证文件的正确读写Unix系统提供了文件记录锁的机制也就是上文中提到过的文件记录锁。为了提供这个功能各个系统都自行实现了API其中POSIX1.x标准规定的是fcntl方法而BSD系列则是规定flock方法SystemV在fcntl方法的基础上构建了lockf函数 fcntl函数 int fcntl(int fildes, int cmd, ...);The commands available for advisory record locking are as follows:F_GETLK Get the first lock that blocks the lock description pointed to by the third argument, arg, taken as a pointer to a struct flock (see above). The information retrieved overwrites the information passed to fcntl in the flock structure. If no lock is found that would prevent this lock from being created, the structure is left unchanged by this function call except for the lock type which is set to F_UNLCK.F_SETLK Set or clear a file segment lock according to the lock description pointed to by the third argument, arg, taken as a pointer to a struct flock (see above). F_SETLK is used to establish shared (or read) locks (F_RDLCK) or exclusive (or write) locks, (F_WRLCK), as well as remove either type of lock (F_UNLCK). If a shared or exclusive lock cannot be set, fcntl returns immediately with EAGAIN.F_SETLKW This command is the same as F_SETLK except that if a shared or exclusive lock is blocked by other locks, the process waits until the request can be satisfied. If a signal that is to be caught is received while fcntl is waiting for a region, the fcntl will be interrupted if the signal han-dler has not specified the SA_RESTART (see sigaction(2)).复制代码前面也介绍过这个函数不过这次会讲解记录锁的内容对于记录所来说cmd参数是F_GETLK、F_SETLK或者FSETLKW第三个参数是一个纸箱flock结构体的指针 struct flock {off_t l_start; /* starting offset */off_t l_len; /* len 0 means until end of file */pid_t l_pid; /* lock owner */short l_type; /* lock type: read/write, etc. */short l_whence; /* type of l_start */ };复制代码基本上也不用讲解了注释早已说明一切。这个结构体就是通过指定文件区域和锁的类型等参数锁定文件。不过需要注意的是l_type实际上是取值SEEK_SET、SEEK_CUR、或SEEK_END。并且上面提到的类型只有两种共享读锁和独占写锁实际上就是读写锁。 F_GETLK参数判断flockptr参数所描述的锁是否会被另一把锁排斥F_SETLK参数设置由flockptr所描述的锁F_SETLKW这是F_SETLK的阻塞版本很容易想到在开发中肯定是先用F_GETLK参数测试是否能建立一把锁而后使用F_SETLK或者F_SETLKW建立锁但是这两者并不是原子操作前面已经讲过非原子操作很容易导致操作冲突。在设置释放锁的时候内核是根据字节数维持锁的范围的也就是说实际上内核只是维护了一个flock结构体的链表然后每次的锁更改都会导致链表被遍历并且合并。对于记录锁的自动继承和释放有3条规则 锁和进程、文件相关联换言之一个进程结束的时候所有的锁全部释放这实际上是exit函数做清理的第二就是文件描述符关闭的时候该文件所有的锁都会关闭fork产生的子进程不继承父进程的锁。因为锁是用于限制多个进程读写同一个文件的如果fork能继承锁那就起不到约束作用了执行exec后新程序继承原执行程序的锁但是close_on_exec则会不一样。其实锁对数据库这种大量读写IO的程序才是最有用的所以基本上锁就可以直接考虑数据库的环境如果数据库的客户端库使用的是同一套锁机制那就能保证文件的共享访问但是建议性锁无法保证其他有权限存取数据库文件的进程读写此文件。而强制性锁则会让进程检查每一个open、read和write函数验证调用进程是否违背了正在访问文件的锁这就是强制性锁和建议性锁的区别。 IO多路转接 前面谈到过对于内核来说IO只有两种方式阻塞和非阻塞阻塞IO会导致CPU等待IO从而浪费等待时间所以系统提供了非阻塞IO但是非阻塞IO带来的问题就是完整IO没有完成为了获取完整的数据应用程序需要重复调用IO操作来确认是否完成也就是轮询。当从一个文件描述符读然后又写到另一个描述符时通常会写出以下代码 while ((n read(STDIN_FILENO, buf, BUFSIZE)) 0)if (write(STDOUT_FILENO, buf, n) ! n)err_sys(write error);复制代码这种循环获取的形式就是轮询非常简单但是消耗了CPU资源并且如果需要有更高的要求比如必须从两个文件描述符读取。典型的应用就是网络守护进程例如Nginx和Telnet这里直接拿原著中的Telnet讲解telnet由于存在两个输入两个输出所以不能使用阻塞式的IO函数开发者的第一反应应该是fork函数使用两个进程每个进程都负责一条读写通道但是这就需要进程同步而多线程编程也同样是这样的问题。另一个方法就是使用一个进程但是使用非阻塞IO读取数据。其基本思想很简单两个描述符都读取但是一直处于循环每次循环都查询一次两个文件描述符如果没有就立刻返回不阻塞这种循环就是典型的轮询这是种非常常见的技术实际上却是非常浪费CPU资源的技术所以目前基本开发以及不能也不推荐了。还有几种技术就是异步IO这种技术实质上就是类似通知当描述符准备完毕后进程通知内核但是实际上目前原生API并不能做到移植所以目前大部分的开发包括Node.js等在内的网络服务基本都是使用第三方或者自己实现线程池。不过目前Linux系统已经有了名为AIO的原生异步IO。现在目前大部分的使用方式就是IO多路转接系统构造一张链表里面存储所有的文件描述符然后调用函数侦听知道其中一个已经准备完毕的时候返回。poll、pselect和select三个函数就是这样执行的。 select和pselect函数 这连个函数是POSIX规定的 int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict errorfds, struct timeval *restrict timeout); int pselect(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict errorfds, const struct timespec *restrict timeout, const sigset_t *restrict sigmask);复制代码第一个参数nfds的意思就是“最大文件描述符编号值1”因为文件描述符都是从0开始的从后面readfds、writefds、errorfds中找出最大描述符编号值并1就是这个参数的值中间三个参数是指向描述符集的指针使用fd_set数据结构表示实际上有下列五个函数 void FD_CLR(fd, fd_set *fdset); void FD_COPY(fd_set *fdset_orig, fd_set *fdset_copy); void FD_ISSET(fd, fd_set *fdset); void FD_SET(fd, fd_set *fdset); void FD_ZERO(fd_set *fdset);复制代码是不是发现比原著多了一个FD_COPY函数实际上就是复制用的无关紧要。最后一个参数就是制定愿意等待的时间长度使用timeval结构体也就是可以指定秒和微妙单位。 timeout NULL永远等待timeout-tv_sec 0 timeout-tv_usec 0不等待timeout-tv_sec ! 0 || timeout-tv_usec ! 0等待指定时间select实际上和描述符本身阻塞无关它只是简化了我们监听一堆文件描述符的繁琐操作除了select以外上面还有一个select的变体pselectpselect和select很像但是select得超时值用timeval结构体定义pselect使用timespec结构pselect可使用可选信号屏蔽字如果sigmask为null则两者一样但是sigmask指向屏蔽字的时候将以原子操作形式安装屏蔽字。 poll函数 除了select以外大家应该还见过poll函数 int poll(struct pollfd fds[], nfds_t nfds, int timeout);复制代码看起来poll函数相对于select更加简洁易懂select函数对三种类型都指定了参数用于构造描述符集但是poll函数使用的则是pollfd结构体数组pollfd结构体如下 struct pollfd {int fd; /* file descriptor */short events; /* events to look for */short revents; /* events returned */ };复制代码nfds参数指定了fds数组的大小从上面的注释中应该也看得出来结构体究竟是怎么构造的events是我们关心fd的事件而revents则是内核设置返回的时候用于说明每个描述符发生了哪些事件。 The event bitmasks in events and revents have the following bits:POLLERR An exceptional condition has occurred on the device or socket. This flag is output only, and ignored if present in the input events bitmask.POLLHUP The device or socket has been disconnected. This flag is output only, and ignored if present in the input events bitmask. Note that POLLHUPand POLLOUT are mutually exclusive and should never be present in the revents bitmask at the same time.POLLIN Data other than high priority data may be read without blocking. This is equivalent to ( POLLRDNORM | POLLRDBAND ).POLLNVAL The file descriptor is not open. This flag is output only, and ignored if present in the input events bitmask.POLLOUT Normal data may be written without blocking. This is equivalent to POLLWRNORM.POLLPRI High priority data may be read without blocking.POLLRDBAND Priority data may be read without blocking.POLLRDNORM Normal data may be read without blocking.POLLWRBAND Priority data may be written without blocking.POLLWRNORM Normal data may be written without blocking.复制代码上面是两个参数可取的值每个系统实现可能存在偏差所以需要自行尝试。 异步I/O 前面讲过非阻塞IO带来的就是轮询前面内容包括前面的章节整合一下可以归纳出以下主流轮询技术 read最原始性能最低的一种重复检查IO状态来完成完整数据的读取也就是前面一小节的开头代码select在read基础上改进的方案通过对文件描述符上的事件状态判断poll使用链表作为文件描述符的存储方式和select类似epoll目前Linux下最高效的IO事件通知机制进入轮询时候如果没有检查到IO事件就会休眠直到事件将其唤醒queue和epoll类似不过是FreeBSD下的虽然轮询满足了非阻塞IO获取完整数据的需求但是依旧是同步的也需要花费CPU用于便利文件描述符或者休眠等待事件发生。所以就有了异步IO目前据笔者所知只有Linux下有AIO技术算是真正原生提供的API。但是实际上是有模拟方式的信号机构提供了异步形式通知事件发生的方法使用一个信号通知进程但是由于信号是有限的如果使用一个信号则进程不知道是哪个文件描述符发生的事件如果用多个信号文件描述符的数量可能远远超出信号的数量。实际上最容易想到的办法就是多线程。让部分线程进行阻塞IO或者非阻塞IO加轮询技术来完成数据获取让另一个线程进行计算而后通过线程间通信将IO得到的数据进行传递就能轻松实现异步IO。 SystemV异步IO SystemV中异步IO是归属给STREAMS系统的他只能用于STREAMS设备和管道异步IO信号是SIGPOLL。实际上由于这种机制本身的限制目前已经找不到Unix环境会去采用它了所以这里也不需要再讲解了。 BSD异步IO 对于BSD系列的系统来说异步IO信号是SIGIO和SIGURG信号的组合SIGIO是通用异步IO的信号SIGURG则是通知网络连接的数据已经到达。 POSIX异步IO POSIX标准对不同类型文件异步IO提供了可移植的模型异步IO使用AIO控制块来描述IO操作。 struct aiocb {int aio_fildes; /* File descriptor */off_t aio_offset; /* File offset */volatile void *aio_buf; /* Location of buffer */size_t aio_nbytes; /* Length of transfer */int aio_reqprio; /* Request priority offset */struct sigevent aio_sigevent; /* Signal number and value */int aio_lio_opcode; /* Operation to be performed */ };复制代码上面是苹果系统下的AIO控制块实现实际上和POSIX规定几乎一样它是继承于FreeBSD3.0的AIO实现从上面可以看出每个字段究竟的意义aio_fildes就是文件描述符读写操作从aio_offset指定的偏移量位置开始对于读操作会将数据复制到aio_buf的缓冲区内对于写操作会从这个缓冲区写入磁盘aio_nbytes字段指定了读写的字节数。除了上面4个字段以外aio_reqprio就是异步IO请求的顺序aio_sigevent就是IO事件完成后如何通知而aio_lio_opcode就是执行的操作。 struct sigevent {int sigev_notify; /* Notification type */int sigev_signo; /* Signal number */union sigval sigev_value; /* Signal value */void (*sigev_notify_function)(union sigval); /* Notification function */pthread_attr_t *sigev_notify_attributes; /* Notification attributes */ };复制代码sigevent结构体是归属于signal信号机制模型中的数据结构其中sigev_notify字段是通知类型 SIGEV_NONE 不通知进程SIGEV_SIGNAL 异步IO完成后产生sigev_signo指定的信号SIGEV_THREAD 异步请求完成后由sigev_notify_function指定的函数被调用int aio_read(struct aiocb *aiocbp); int aio_write(struct aiocb *aiocbp);复制代码在异步IO之前需要先初始化AIO控制块当函数返回成功时候异步IO请求就已经被放在了等待处理队列中。这些返回值与实际IO擦做的结果没有任何关系如果想要强制所有等待中的异步操作不等待直接写入存储则调用aio_fsync函数当然好像aio_fsync函数并不是非常广泛所以在使用的时候记得运行时检查。为了获取一个异步读写的完成状态可以调用aio_error函数 int aio_error(const struct aiocb *aiocbp);复制代码返回如下 返回值为0异步操作成功使用aio_return函数获得返回值返回值为-1对aio_error操作失败返回值为EINPROGRESS读写操作仍处于等待状态ssize_t aio_return(struct aiocb *aiocbp);复制代码记住在aio_error检查已经成功之前不要调用aio_return函数而且需要当心每个异步操作只能调用一次aio_return函数。如果在其他操作完成之后异步操作还未完成那可以使用 int aio_suspend(const struct aiocb *const list[], int nent, const struct timespec *timeout);复制代码aio_suspend函数会阻塞当前进程直到操作完成一般情况下很少会使用。如果我们想要取消已经处于进行中的异步操作可以使用如下函数 int aio_cancel(int fildes, struct aiocb *aiocbp);复制代码这个函数会返回4个返回值 AIO_ALLDONE所有操作已经完成AIO_CANCELED所有操作已经取消AIO_NOtCANCELED至少有一个请求没有取消-1函数本身失败除了上述函数以外还有一个函数也被包含在异步请求函数中但是实际上很少见到所以这里就不多做讲解。 readv和writev函数 ssize_t readv(int d, const struct iovec *iov, int iovcnt); ssize_t writev(int fildes, const struct iovec *iov, int iovcnt);复制代码这两个函数用于在一次读写中读写多个非连续的缓冲区也就是说可以将传统的多个函数读写调用压缩到一个这连个函数第二个参数就是一个指向iovec结构体的指针实际上是一个指向数组的指针 struct iovec {char *iov_base; /* Base address. */size_t iov_len; /* Length. */ };复制代码第三个参数就是数组的长度。iov数组中的元素最大值就是IOV_MAX。 存储映射IO 存储映射IO能将一个磁盘文件映射到存储空间中的一个缓冲区上于是当从缓冲区中读取数据的时候就等同于读取文件。Unix系统提供了此类函数 void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);复制代码addr指定映射存储区的起始地址。通常为0也就是系统自动分配区域。fd参数指定被映射文件的文件描述符也就代表必须先打开这个文件。prot参数指定了映射存储区的保护要求如下|prot|说明||----|---||PROT_READ|存储区可读||PROT_WRITE|存储区可写||PROT_EXEC|存储区可执行||PROT_NONE|存储区不可访问|当然这个参数的指定必然是基于文件描述符的打开方式的很容易明白因为存储映射IO技术本质上还是基于文件描述符的所以不可能绕过文件描述符的限制读写。flag参数影响映射存储区的多种属性如下就是可选值 MAP_ANONYMOUS Synonym for MAP_ANON.MAP_ANON Map anonymous memory not associated with any specific file. The offset argument is ignored. Mac OS X specific: the file descriptor usedfor creating MAP_ANON regions can be used to pass some Mach VM flags, and can be specified as -1 if no such flags are associated with theregion. Mach VM flags are defined in mach/vm_statistics.h and the ones that currently apply to mmap are:VM_FLAGS_PURGABLE to create Mach purgable (i.e. volatile) memoryVM_MAKE_TAG(tag) to associate an 8-bit tag with the regionmach/vm_statistics.h defines some preset tags (with a VM_MEMORY_ prefix). Users are encouraged to use tags between 240 and 255. Tagsare used by tools such as vmmap(1) to help identify specific memory regions.VM_FLAGS_SUPERPAGE_SIZE_* to use superpages for the allocation. See mach/vm_statistics.h for supported architectures and sizes (oruse VM_FLAGS_SUPERPAGE_SIZE_ANY to have the kernel choose a size). The specified size must be divisible by the superpage size (except forVM_FLAGS_SUPERPAGE_SIZE_ANY), and if you use MAP_FIXED, the specified address must be properly aligned. If the system cannot satisfy therequest with superpages, the call will fail. Note that currently, superpages are always wired and not inherited by children of the process.MAP_FILE Mapped from a regular file. (This is the default mapping type, and need not be specified.)MAP_FIXED Do not permit the system to select a different address than the one specified. If the specified address cannot be used, mmap() will fail.If MAP_FIXED is specified, addr must be a multiple of the pagesize. If a MAP_FIXED request is successful, the mapping established bymmap() replaces any previous mappings for the process pages in the range from addr to addr len. Use of this option is discouraged.MAP_HASSEMAPHORE Notify the kernel that the region may contain semaphores and that special handling may be necessary.MAP_PRIVATE Modifications are private (copy-on-write).MAP_SHARED Modifications are shared.MAP_NOCACHE Pages in this mapping are not retained in the kernels memory cache. If the system runs low on memory, pages in MAP_NOCACHE mappings willbe among the first to be reclaimed. This flag is intended for mappings that have little locality and provides a hint to the kernel thatpages in this mapping are unlikely to be needed again in the near future.复制代码这就不讲解了原著上已经讲解的足够清楚了。调用mprotect可以更改现有映射的权限 int mprotect(void *addr, size_t len, int prot);复制代码也就是一个修改映射区域权限的函数当页已经修改完毕可以调用msync函数冲洗到被映射的文件中。 int msync(void *addr, size_t len, int flags);复制代码基本就和fsync函数差不多也不多说了基本上都在Unix手册上当进程终止的之后自然会自动解除存储区的映射或者可以调用munmap函数解除 int munmap(void *addr, size_t len);复制代码munmap函数删除了指定地址的映射如果继续对其进行读写会导致无效内存引用。并且这个函数不会冲洗缓冲区内容到文件所以需要小心使用。
http://www.pierceye.com/news/209488/

相关文章:

  • 建设工程许可证在那个网站办金融行业网站制作
  • 邢台专业做网站价格信息流广告是什么
  • 网站开发的母的目的和意义.建设购物平台网站
  • 立方米网站建设做淘宝客网站用什么程序好
  • 怎样做网站挣钱建筑资料软件
  • 涿州建设局网站苏州市高新区建设局网站
  • 个人soho要怎么做企业网站成都包装设计公司
  • 网站开发 chrome浏览器崩溃ruhe用dw做网站
  • 全屏网站 图片优化个人网站cms系统
  • 做我女朋友程序网站邵东做网站
  • 建设网站如何挂到网上wordpress首页添加幻灯
  • 汕头正规网站建设模板总部城乡建设网站 资料员
  • vs 2017c 怎么建设网站网站建设的数字化和互联网化
  • 南昌网站设计公司海南营销网站建设
  • 购物网站素材个人搭建网站教程
  • 青岛网站建设哪里好模板建站服务公司
  • 青色网站欣赏wordpress中文购物
  • 建站培训全国住房与城乡建设部网站
  • 唐山网站建设方案策划沧州网站建设联系电话
  • 网页制作和网站开发实验报告logo设计品牌
  • 摄影后期教程网站百度指数1000搜索量有多少
  • wp网站建设模板什么是网站的原型
  • 园林绿化网站建设上海著名室内设计公司
  • 大连市住房与城乡建设部网站公司要制作网站
  • 郑州做网站七彩科技企业网站做的漂亮
  • 如何用ps做网站页面设计企业网站备案价格
  • 禅城网站建设价格青岛企业自助建站系统
  • 平阳住房和城乡建设厅网站建设银行龙卡信用卡在境外网站支付
  • 关于网站开发的论文软件开发合同模板免费
  • 军队房地产与建设工程法律实务在哪个网站可以购买深圳市盐田区住房建设局网站