Nginx源码阅读(进程间通信)
来源:互联网 发布:动画创意广告软件 编辑:程序博客网 时间:2024/05/16 05:13
共享内存
/* src/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; /* unsigned exists:1; */} ngx_shm_t;ngx_int_t ngx_shm_alloc(ngx_shm_t *shm);void ngx_shm_free(ngx_shm_t *shm);
/* src/os/unix/ngx_shmem.c */#if (NGX_HAVE_MAP_ANON)ngx_int_tngx_shm_alloc(ngx_shm_t *shm){ // mmap和munmap的定义:http://www.man7.org/linux/man-pages/man2/mmap.2.html 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;}voidngx_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); }}#elif (NGX_HAVE_MAP_DEVZERO)ngx_int_tngx_shm_alloc(ngx_shm_t *shm){ ngx_fd_t fd; fd = open("/dev/zero", O_RDWR); if (fd == -1) { ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, "open(\"/dev/zero\") failed"); return NGX_ERROR; } shm->addr = (u_char *) mmap(NULL, shm->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (shm->addr == MAP_FAILED) { ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, "mmap(/dev/zero, MAP_SHARED, %uz) failed", shm->size); } if (close(fd) == -1) { ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, "close(\"/dev/zero\") failed"); } return (shm->addr == MAP_FAILED) ? NGX_ERROR : NGX_OK;}voidngx_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); }}#elif (NGX_HAVE_SYSVSHM)#include <sys/ipc.h>#include <sys/shm.h>ngx_int_tngx_shm_alloc(ngx_shm_t *shm){ int id; /* shmget的定义:http://www.man7.org/linux/man-pages/man2/shmget.2.html shmat和shmdt的定义:http://www.man7.org/linux/man-pages/man2/shmop.2.html shmctl的定义:http://www.man7.org/linux/man-pages/man2/shmctl.2.html */ id = shmget(IPC_PRIVATE, shm->size, (SHM_R|SHM_W|IPC_CREAT)); if (id == -1) { ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, "shmget(%uz) failed", shm->size); return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, shm->log, 0, "shmget id: %d", id); shm->addr = shmat(id, NULL, 0); if (shm->addr == (void *) -1) { ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, "shmat() failed"); } if (shmctl(id, IPC_RMID, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, "shmctl(IPC_RMID) failed"); } return (shm->addr == (void *) -1) ? NGX_ERROR : NGX_OK;}voidngx_shm_free(ngx_shm_t *shm){ if (shmdt(shm->addr) == -1) { ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, "shmdt(%p) failed", shm->addr); }}#endif
原子操作
不支持原子库下的原子操作
/* src/os/unix/ngx_atomic.h */#define NGX_HAVE_ATOMIC_OPS 0typedef int32_t ngx_atomic_int_t;typedef uint32_t ngx_atomic_uint_t;typedef volatile ngx_atomic_uint_t ngx_atomic_t;#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1)static ngx_inline ngx_atomic_uint_tngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, ngx_atomic_uint_t set){ if (*lock == old) { *lock = set; return 1; } return 0;}static ngx_inline ngx_atomic_int_tngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add){ ngx_atomic_int_t old; old = *value; *value += add; return old;}#define ngx_memory_barrier()#define ngx_cpu_pause()
x86架构下的原子操作
/* src/os/unix/ngx_atomic.h */typedef int32_t ngx_atomic_int_t;typedef uint32_t ngx_atomic_uint_t;typedef volatile ngx_atomic_uint_t ngx_atomic_t;#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1)#if ( __SUNPRO_C )#define NGX_HAVE_ATOMIC_OPS 1ngx_atomic_uint_tngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, ngx_atomic_uint_t set);ngx_atomic_int_tngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add);/* * Sun Studio 12 exits with segmentation fault on '__asm ("pause")', * so ngx_cpu_pause is declared in src/os/unix/ngx_sunpro_x86.il */voidngx_cpu_pause(void);/* the code in src/os/unix/ngx_sunpro_x86.il */#define ngx_memory_barrier() __asm (".volatile"); __asm (".nonvolatile")#else /* ( __GNUC__ || __INTEL_COMPILER ) */#define NGX_HAVE_ATOMIC_OPS 1#include "ngx_gcc_atomic_x86.h"#endif
/* src/os/unix/ngx_gcc_atomic_x86.h */#if (NGX_SMP)#define NGX_SMP_LOCK "lock;"#else#define NGX_SMP_LOCK#endif/* * "cmpxchgl r, [m]": * * if (eax == [m]) { * zf = 1; * [m] = r; * } else { * zf = 0; * eax = [m]; * } * * * The "r" means the general register. * The "=a" and "a" are the %eax register. * Although we can return result in any register, we use "a" because it is * used in cmpxchgl anyway. The result is actually in %al but not in %eax, * however, as the code is inlined gcc can test %al as well as %eax, * and icc adds "movzbl %al, %eax" by itself. * * The "cc" means that flags were changed. */static ngx_inline ngx_atomic_uint_tngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, ngx_atomic_uint_t set){ u_char res; __asm__ volatile ( NGX_SMP_LOCK " cmpxchgl %3, %1; " " sete %0; " : "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory"); return res;}/* * "xaddl r, [m]": * * temp = [m]; * [m] += r; * r = temp; * * * The "+r" means the general register. * The "cc" means that flags were changed. */#if !(( __GNUC__ == 2 && __GNUC_MINOR__ <= 7 ) || ( __INTEL_COMPILER >= 800 ))/* * icc 8.1 and 9.0 compile broken code with -march=pentium4 option: * ngx_atomic_fetch_add() always return the input "add" value, * so we use the gcc 2.7 version. * * icc 8.1 and 9.0 with -march=pentiumpro option or icc 7.1 compile * correct code. */static ngx_inline ngx_atomic_int_tngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add){ __asm__ volatile ( NGX_SMP_LOCK " xaddl %0, %1; " : "+r" (add) : "m" (*value) : "cc", "memory"); return add;}#else/* * gcc 2.7 does not support "+r", so we have to use the fixed * %eax ("=a" and "a") and this adds two superfluous instructions in the end * of code, something like this: "mov %eax, %edx / mov %edx, %eax". */static ngx_inline ngx_atomic_int_tngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add){ ngx_atomic_uint_t old; __asm__ volatile ( NGX_SMP_LOCK " xaddl %2, %1; " : "=a" (old) : "m" (*value), "a" (add) : "cc", "memory"); return old;}#endif/* * on x86 the write operations go in a program order, so we need only * to disable the gcc reorder optimizations */#define ngx_memory_barrier() __asm__ volatile ("" ::: "memory")/* old "as" does not support "pause" opcode */#define ngx_cpu_pause() __asm__ (".byte 0xf3, 0x90")
自旋锁
/* src/core/ngx_spinlock.c */voidngx_spinlock(ngx_atomic_t *lock, ngx_atomic_int_t value, ngx_uint_t spin){#if (NGX_HAVE_ATOMIC_OPS) ngx_uint_t i, n; for ( ;; ) { // lock为0表示锁是被释放的,lock不为0表示锁是被某个进程持有的 if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, value)) { return; } if (ngx_ncpu > 1) { for (n = 1; n < spin; n <<= 1) { // 检查锁是否被释放的频率会越来越小 for (i = 0; i < n; i++) { ngx_cpu_pause(); } if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, value)) { return; } } } /* #if (NGX_HAVE_SCHED_YIELD) // sched_yield的定义:http://www.man7.org/linux/man-pages/man2/sched_yield.2.html #define ngx_sched_yield() sched_yield() #else #define ngx_sched_yield() usleep(1) #endif */ ngx_sched_yield(); // 暂时让出处理器 }#else#if (NGX_THREADS)#error ngx_spinlock() or ngx_atomic_cmp_set() are not defined !#endif#endif}
0 0
- Nginx源码阅读(进程间通信)
- nginx源码分析--nginx进程间通信
- nginx源码分析--nginx进程间通信
- nginx源码学习(五)进程间的通信
- Nginx源码阅读(worker进程处理http请求流程)
- android系统源码阅读--进程间通信Binder机制
- Nginx进程间通信
- nginx 进程间通信
- Nginx 进程间通信
- nginx 源码分析阅读笔记-进程管理
- Nginx源码分析-master和worker进程间的通信
- Nginx源码分析--master和worker进程间的通信
- Nginx源码分析-master和worker进程间的通信
- nginx源码分析--进程间通信机制 & 同步机制
- nginx源码学习——进程间通信机制
- nginx源码分析1———进程间的通信机制一(信号量)
- nginx源码分析1———进程间的通信机制二(自旋锁)
- nginx源码分析1———进程间的通信机制三(mmap)
- gdufe acm 1057 leftmost digit
- 【Hibernate】查询缓存
- dupestring
- hive的dual表
- go语言程序初学
- Nginx源码阅读(进程间通信)
- 皮克定理
- 分片哈希piecewise hashing
- 8种Java排序算法整理
- AOP之 Filter实用
- 350. Intersection of Two Arrays II
- 概述
- JZOJ 4937 【GDKOI2017模拟1.12】与运算
- linux电源管理架构