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

网站制作与建设教程下载美发店网站源码

网站制作与建设教程下载,美发店网站源码,深圳企业官网网站建设哪家好,logo设计思路共享内存 共享内存结构与接口定义nginx共享内存在操作系统上的兼容性设计互斥锁锁的结构体锁的一系列操作#xff08;core/ngx_shmtx.c#xff09;创建锁 原子操作nginx的上锁操作尝试加锁获取锁释放锁强迫解锁唤醒等待进程 slab共享内存块管理nginx的slab大小规格内存池结构… 共享内存 共享内存结构与接口定义nginx共享内存在操作系统上的兼容性设计互斥锁锁的结构体锁的一系列操作core/ngx_shmtx.c创建锁 原子操作nginx的上锁操作尝试加锁获取锁释放锁强迫解锁唤醒等待进程 slab共享内存块管理nginx的slab大小规格内存池结构体共享内存池结构体slots分配共享内存池 共享内存结构与接口定义 正常来说通过malloc函数申请的内存都是进程私有的内存但是Linux会提供共享内存的系统调用如mmap和munmap等 Nginx基于Linux提供的系统调用封装了共享内存的数据结构以及共享内存的创建与释放函数其共享内存结构和接口定义如下os/unix/ngx_shmem.h typedef struct { u_char *addr; //指向申请的共享内存块首地址size_t size; //共享内存块大小ngx_str_t name; //共享内存块名字ngx_log_t *log; //共享内存块日志ngx_uint_t exists;//标志是否已经存在 } ngx_shm_t;//共享结构//以下共享接口 ngx_int_t ngx_shm_alloc(ngx_shm_t *shm);//创建共享内存块 void ngx_shm_free(ngx_shm_t *shm);//释放共享内存块ngx_int_tngx_shm_alloc(ngx_shm_t *shm) { shm-addr (u_char *) mmap(NULL, shm-size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0); //创建 if (shm-addr MAP_FAILED) { //错误处理ngx_log_error(NGX_LOG_ALERT, shm-log, ngx_errno, mmap(MAP_ANON|MAP_SHARED, %uz) failed, shm-size); return NGX_ERROR; } return NGX_OK;//成功返回 }void ngx_shm_free(ngx_shm_t *shm) { if (munmap((void *) shm-addr, shm-size) -1)//是否成功 { //失败处理记录ngx_log_error(NGX_LOG_ALERT, shm-log, ngx_errno, munmap(%p, %uz) failed, shm-addr, shm-size); } }nginx共享内存在操作系统上的兼容性设计 #if (NGX_HAVE_MAP_ANON)//匿名共享内存 ……… #elif (NGX_HAVE_MAP_DEVZERO)//文件共享内存 ……… #elif (NGX_HAVE_SYSVSHM)//IPC System V共享内存 ……… #endif互斥锁 并发进程访问共享内存时需要加锁。nginx提供了互斥锁的机制保证了正确的共享内存的访问。nginx的进程主要是通过ngx_shmtx_t进行加锁、解锁等操作。nginx实现的时候如果操作系统提供原子操作机制就使用操作系统的原子操作实现互斥锁否则nginx采用文件锁实现互斥。 互斥锁模型 锁的结构体 //core/ngx_shmtx.h typedef struct { ngx_atomic_t lock;//0为锁开空闲其它进程号已上锁#if (NGX_HAVE_POSIX_SEM) //如果有SEM信号量ngx_atomic_t wait;//等待共享内存进程总数#endif } ngx_shmtx_sh_t;上锁、解锁的结构体模型 typedef struct {#if (NGX_HAVE_ATOMIC_OPS) //若有原子操作…………#if (NGX_HAVE_POSIX_SEM) //如果有信号量 …………#endif#else …………#endif ngx_uint_t spin; } ngx_shmtx_t;typedef struct {#if (NGX_HAVE_ATOMIC_OPS) //若有原子操作ngx_atomic_t *lock;//进程内指向共享内存锁的地址#if (NGX_HAVE_POSIX_SEM) //如果有信号量 ngx_atomic_t *wait; //指向共享内存等待进程总数ngx_uint_t semaphore; //是否使用信号量1使用sem_t sem;//sem_t信号量可用于线程之中也可用于进程#endif#else //操作系统无原子操作和信号量支持用文件ngx_fd_t fd; u_char *name;#endif ngx_uint_t spin; } ngx_shmtx_t;锁的一系列操作core/ngx_shmtx.c ngx_int_t ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name);//创建锁void ngx_shmtx_destroy(ngx_shmtx_t *mtx);//销毁锁void ngx_shmtx_lock(ngx_shmtx_t *mtx);//获取锁ngx_uint_t ngx_shmtx_trylock(ngx_shmtx_t *mtx);//尝试加锁void ngx_shmtx_unlock(ngx_shmtx_t *mtx);//释放锁ngx_uint_t ngx_shmtx_force_unlock(ngx_shmtx_t *mtx, ngx_pid_t pid);//强制解锁static voidngx_shmtx_wakeup(ngx_shmtx_t *mtx)//唤醒等进程 临界区管理的基本思路 ①找到临界区 ②在临界区前面增加一段用于进行检查的代码当不满足进入临界区的条件就不进入直到满足条件才进入称为进入区(entry section)。 ③在临界区后面加上一段称为离开区(exit section)的代码作为善后处理。基本形式如下 创建锁 ngx_int_t ngx_shmtx_create( ngx_shmtx_t *mtx,ngx_shmtx_sh_t *addr, u_char *name);//创建锁//ngx_shmtx_t *mtx是进程操作锁结构地址 //ngx_shmtx_sh_t *addr是共享内存中保存的锁结构地址 //u_char *name名字用于区别不同锁地址{ mtx-lock addr-lock; //将共享内存锁信息储存到进程操作锁结构体中 if (mtx-spin (ngx_uint_t) -1) { return NGX_OK; } mtx-spin 2048;//自旋次数指定#if (NGX_HAVE_POSIX_SEM) //如果是信号量初始化sem为1并将semaphore设为1mtx-wait addr-wait; if (sem_init(mtx-sem, 1, 0) -1) { ngx_log_error(NGX_LOG_ALERT, ngx_cycle-log, ngx_errno, sem_init() failed); } else { mtx-semaphore 1; } #endif return NGX_OK; }进程操作锁结构需要获得保存共享内存锁的信息对于自旋锁 1)保存共享内存锁的lock 2设置自旋锁的自旋次数以便于后续进行加锁、解锁等操作 mtx-lock addr-lock; if (mtx-spin (ngx_uint_t) -1) { //已经加锁了 return NGX_OK; } mtx-spin 2048;//nginx设置的进程自旋次数对于信号量 1)保存共享内存锁的保存wait 2设置信号量的semaphore或sem的值以便于后续进行加锁、解锁等操作 mtx-wait addr-wait; //保存指向保存共享内存进程总数指针 if (sem_init(mtx-sem, 1, 0) -1) //线程信号量初始化失败 { ngx_log_error(NGX_LOG_ALERT, ngx_cycle-log, ngx_errno, sem_init() failed); } else // 线程信号量初始化成功初始化semaphore为1 { mtx-semaphore 1; //使用信号量 }其它可能需要记录的调试信息以及可能的错误处理等 原子操作 计算机系统并发的基础 两个原子操作 ngx_atomic_cmp_seta,old,new:如果*aold将*a赋值为new返回1。否则返回0。ngx_atomic_cmp_set(mtx-lock, 0, ngx_pid)原子操作若*mtx-lock为0即将*mtx-lock赋值为ngx_pid。ngx_atomic_fetch_addold,v将*old加上v并返回*old。ngx_atomic_fetch_add(mtx-wait, 1)将*mtx-wait加上1并返回加之前的*mtx-wait值。nginx的上锁操作 当共享内存lock为0表示空闲时可以上锁。对于上锁的操作Nginx将其标准化为将lock当其为0时设为进程的PID。即 *mtx-lock 0 ngx_atomic_cmp_set(mtx-lock, 0, ngx_pid)。尝试加锁 ngx_uint_tngx_shmtx_trylock(ngx_shmtx_t *mtx) { return (*mtx-lock 0 ngx_atomic_cmp_set(mtx-lock, 0, ngx_pid)); }获取锁 进程自旋锁的获取 当共享内存lock为0表示空闲时可以上锁。对于上锁的操作nginx将其标准化为将lock当其为0时设为进程的PID。即 *mtx-lock 0 ngx_atomic_cmp_set(mtx-lock, 0, ngx_pid)。 因为*mtx-lock 为0时可能有很多进程都来上锁但只能有一个进程会成功上锁。因此对上锁进程来讲以上上锁操作可能不成功。 此时当有多个CPU时上锁进程可以等待一段T时间后再次尝试上锁操作。Ngnix对T的构造有其独特的方法。 上锁失败放弃使用CPU void ngx_shmtx_lock(ngx_shmtx_t *mtx)//自旋锁 {ngx_uint_t i, n; //初始化变量 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle-log, 0, shmtx lock); for(;;){//不断循环进行自旋方式加锁#if (NGX_HAVE_POSIX_SEM)信号量方式加锁wait记录等待共享进程总数等待进程挂入sem等待队列#endifngx_sched_yield();//优化方式放弃CPU} }//自旋式加锁 for ( ;; ) { if (*mtx-lock 0 ngx_atomic_cmp_set(mtx-lock, 0, ngx_pid)) { return; } //成功上锁返回 if (ngx_ncpu 1) { //当有多个CPU时等待T时间后再次尝试上锁 for (n 1; n mtx-spin; n 1){//构造等待时间T再多次尝试上锁{ for (i 0; i n; i) { //每次都有等待时间T 每次内循环等待次数不一样ngx_cpu_pause(); //借用CPU机制优化自旋等待} if (*mtx-lock 0 ngx_atomic_cmp_set(mtx-lock, 0, ngx_pid)) { return; } //再次尝试上锁若成功则返回} } ngx_sched_yield();//优化上锁失败放弃使用CPU 。调度选中后再次自旋上锁(为啥)。 }信号量处理锁的获取 如果是信号量 等待共享内存进程总数预先原子性操作加一当lock为0表示空闲时可以上锁。按照nginx标准化上锁操作也就是将lock当其为0时设为进程的PID。即 *mtx-lock 0 ngx_atomic_cmp_set(mtx-lock, 0, ngx_pid)。 如果成功将等待共享内存进程数减一因已成功上锁预计加需扣除返回。 (void) ngx_atomic_fetch_add(mtx-wait, 1); //原子操作预加一if (*mtx-lock 0 ngx_atomic_cmp_set(mtx-lock, 0, ngx_pid)){ //上锁成功了 (void) ngx_atomic_fetch_add(mtx-wait, -1); //原子操作减一 return; //返回}如果上锁失败将该加锁进程挂入sem的等待队列中。由于挂入sem的等待队列操作可能失败为了确保1中的加一操作与实际等待进程总数一致性需要不断尝试挂入等待队列操作直至成功挂入为止。否则数据将不一致。挂入等待队列的某进程由释放锁某进程唤醒。 while (sem_wait(mtx-sem) -1) {//如果失败再次进行挂入sem等待队列操作 ngx_err_t err; err ngx_errno; //获取错误原因 if (err ! NGX_EINTR) { //若是系统原因进行错误日志处理后终止尝试 ngx_log_error(NGX_LOG_ALERT, ngx_cycle-log, err, sem_wait() failed while waiting on shmtx);break; } } ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle-log, 0, shmtx awoke); continue; //进行下一个循环 释放锁 void ngx_shmtx_unlock(ngx_shmtx_t *mtx);//释放锁 { if (mtx-spin ! (ngx_uint_t) -1) //调试信息处理{ ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle-log, 0,shmtx unlock); } if (ngx_atomic_cmp_set(mtx-lock, ngx_pid, 0)) {//将lock设为0就是释放ngx_shmtx_wakeup(mtx); //唤醒等待进程} }强迫解锁 ngx_uint_tngx_shmtx_force_unlock(ngx_shmtx_t *mtx, ngx_pid_t pid)//强迫解锁 { ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle-log, 0, “shmtx forced unlock”); //记录调试信息if (ngx_atomic_cmp_set(mtx-lock, pid, 0)) { //共享内存lock为0空闲 ngx_shmtx_wakeup(mtx); //唤醒等待共享进程进程 return 1; } return 0;//强制失败返回0 }唤醒等待进程 如果有信号量支持//因为只有有信号量支持时才有sem等待队列 如果没有标记使用信号量没有构造等待队列返回。 #if (NGX_HAVE_POSIX_SEM)//由信号量支持 if (!mtx-semaphore) { return; } ………//剩下的其它操作实现 #endif不断使用ngx_atomic_cmp_set(mtx-wait, wait, wait - 1)对mtx-wait减一操作直至成功将mtx-wait原子操作减一。 for ( ;; ) { //不断尝试进行以下方式原子操作减一wait *mtx-wait; if ((ngx_atomic_int_t) wait 0) { return; } //没有等待共享内存进程返回。if (ngx_atomic_cmp_set(mtx-wait, wait, wait - 1)) { break; //成功原子操作减一终止尝试原子减一。 } }从sem等待队列中唤醒一个进程 if (sem_post(mtx-sem) -1) { //失败唤醒一个进程错误日志处理ngx_log_error(NGX_LOG_ALERT, ngx_cycle-log, ngx_errno, sem_post() failed while wake shmtx); }slab共享内存块管理 nginx设计与实现了一种基于slab理念的共享内存块机制并提供了创建共享内存块、从共享内存块中申请与释放内存的API。其结构体包括core/ngx_slab.h以及core/ngx_slab.c ngx_slab_page_s内存块管理结构体 ngx_slab_stat_t内存页使用信息管理结构体 ngx_slab_pool_t共享内存块结构体 typedef struct ngx_slab_page_s ngx_slab_page_t; nginx的slab大小规格 内存池结构体 typedef struct ngx_slab_page_s ngx_slab_page_t; struct ngx_slab_page_s { uintptr_t slab; ngx_slab_page_t *next; //后向uintptr_t prev;//前向 };typedef struct { ngx_uint_t total; //总数 ngx_uint_t used; //使用总数 ngx_uint_t reqs; //请求总数 ngx_uint_t fails;//失败总数 } ngx_slab_stat_t;// 共享内存池结构体 typedef struct { ngx_shmtx_sh_t lock; //内存锁 size_t min_size; //可以分配最小内存大小即为8size_t min_shift; //最小slab内存的幂数即min_size2^ min_shiftngx_slab_page_t *pages; //指向第一页的管理结构ngx_slab_page_t *last; //指向最后页的管理结构ngx_slab_page_t free; //指向空闲首页的一个结点ngx_slab_stat_t *stats; //指向记录各种规格slab统计信息链表ngx_uint_t pfree; //空闲总页数u_char *start; //空闲页始址u_char *end;//空闲末址ngx_shmtx_t mutex; //进程操作锁结构u_char *log_ctx; u_char zero; unsigned log_nomem:1; void *data; void *addr;//共享内存池结构地址 } ngx_slab_pool_t;共享内存池结构体slots 1.初始化共享内存池管理结构体各数据成员的值理清控制管理关系。 2.分出控制管理结构后剩余的即为可以共享分配的内存池。 管理不同规格的ngx_slab_page_t的首地址nginx用宏ngx_slab_slots(pool)描述了这一大小位置关系 按情形初始化共享池为0xA5除共享池管理结构外 初始化管理不同大小slab的ngx_slab_page_t 按情形初始化ngx_slab_stat_t 计算总页数pages 初始化pool的pages 初始化pool的free 初始化管理空页的首个ngx_slab_page_t 初始化pool的start 初始化pool的start因对齐修正总空闲数 初始化pool的其它成员 分配共享内存池 理论上每个大小为KB的系统物理页可以包含k/m个大小为mB规格的slab块。为了标明一个系统物理页中含有的大小为mB规格slab块的占有情况Nginx为每个系统物理页使用bitmap描述其含有的每个slab块是否空闲。这样每个大小为KB的系统物理页需要k/m位描述其每个slab的空闲占有情况如位1表示占有如位0表示空闲。对于小块内存大小8Byte~32Byte,需要较多位512b~128b。nginx在内存首页开辟固定区域码放这些bitmap。对于精确内存大小为64Byte,需要64b。nginx使管理内存页的ngx_slab_page_t结构体的slab字段作为bitmap。对于大块内存大小128Byte~2048Byte需要32b~2b使用slab的前32位作为bitmap void* ngx_slab_alloc(ngx_slab_pool_t *pool, size_t size) {void *p; ngx_shmtx_lock(pool-mutex);//互斥分配p ngx_slab_alloc_locked(pool, size); ngx_shmtx_unlock(pool-mutex); //互斥分配return p; }
http://www.dnsts.com.cn/news/115065.html

相关文章:

  • 做网站跳转怎么收费浙江创都建设有限公司网站
  • 中国建设人才服务信息网是正规网站广西桂林
  • 什么行业做网站搜索番禺网站开发公司
  • 企业网站小程序源码福田庆三案例照
  • 深圳网站制作880传媒公司商业计划书
  • 如何上传模板到网站视频链接生成网站
  • 珠海华兴建设工程有限公司网站会员管理系统软件哪个好
  • vs简易新闻建设网站找代加工产品哪个网
  • 中国临沂网站优化西安的商城网站设计
  • 网站开发需要什么专业广告投放系统源码
  • 网站建设制作方法wordpress
  • 郑州seo网站有优化住房和城乡建设部网站监理工程师
  • 服务器网站建设流程网页设计与制作专业介绍
  • 外贸企业公司网站建设用户体验 网站 外国
  • 怎么做批量的网站检查app软件定制开发平台
  • 晚上网站推广软件免费版网站彩票代理怎么做
  • 网站的提交重置按钮怎么做wordpress站点地址灰显
  • 做网站不搭建本地环境电子商务平台建设内容有哪些
  • 驻马店网站建设服务器iis搭建网站
  • 广州网站建设技术托管温州建设局网站
  • 遵义网站设计最好看免费观看高清大全知否知否
  • 一家专门做爆品印刷的网站请选择一个网站制作软件
  • 贵州省住房和建设厅网网站阿里云域名注册入口官网
  • 个人租车网站源码个人业务网站后台
  • 厦门公司注册网址seo根据什么具体优化
  • 网站建设模板之家免费下载wordpress 悬浮播放器
  • wordpress新站注意事项优化seo教程技术
  • 微网站站点名称做网站视频背景
  • 在网站中加入锚链接应该怎么做网站开发所需要的书籍
  • 黄山网站建设方案西安seo优化