Linux Concurrent Programming —— Thread【Beta1-Updating】_firo_baidu的博客-CSDN博客_linux concurrent


本站和网页 https://blog.csdn.net/firo_baidu/article/details/6363203 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

Linux Concurrent Programming —— Thread【Beta1-Updating】_firo_baidu的博客-CSDN博客_linux concurrent
Linux Concurrent Programming —— Thread【Beta1-Updating】
firo_baidu
于 2011-04-26 08:41:00 发布
4611
收藏
分类专栏:
Linux
文章标签:
thread
linux
signal
ubuntu
allocation
initialization
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/firo_baidu/article/details/6363203
版权
Linux
专栏收录该内容
7 篇文章
0 订阅
订阅专栏
                                     Linux Concurrent Programming —— Thread
                                                                                                                                             ——by firo 2011.4.26
Reference
Google
man  7 pthreads
Professional Linux Kernel Architecture【PLKA】
Understanding The Linux Kernel 3e 【ULK 3e】
Computer Systems: A Programmer‘s Perspective 2e【CS:APP 2e】
Advanced Programming in the Unix Environment Second Edition 【APUE 2e】
Unix Network Programming The Sockets Networking API VOLUME 1 Third Edition【UNPv1 3e】
The Linux Programming inTerface A Linux and UNIX System Programming Handbook 【TLPI】
Thread Implementation Models——线程实现模型
What is the Kernel Scheduling Entities (KSE)?
Kernel Scheduling Entities内核调度实体。
“A kernel scheduling entity (KSE) is a “virtual CPU” granted to the process for the purpose of executing threads.  A thread that is currently executing is always associated with exactly one KSE, whether executing in user space or in the kernel.”(摘自Free BSD man手册)
KSE——虚拟的CPU,使得进程可以执行多个线程;正在执行的线程,无论它是在用户模式还是内核模式,它总是和一个确定的KSE相关联。
TLPI中关于KSE的描述:kernel分配CPU和其他系统资源给KSE。
Many-to-one (M:1) implementations (user-level threads)
关于线程的实现的所有操作(Many):线程创建,结束,Mutex同步,Condition variabled等等都由库(1)来实现。
优点:【1】因为不涉及System call,所有的操作也就非常的快啦~~【2】不需要内核支持,所以移植性非常高,除DOS那一辈的都行~
缺点:【1】你也不能总在用户模式执行吧,所以问题来了,当你执行一个System call时,好家伙,Context switch上下文切换到了kernel模式了,User-level的所有操作都Stop了,甭管你有多少个线程全停——谁叫你是User-level用户模式的,性能损耗不言自明。【2】kernel无法识别到这些用户级的Thread,所以kernel就不能切换他们了,分配他们倒不同的核上了(多核CPU),也无法调整线程的优先级,这些都由库来包办了,显然不是全局最优~~
One-to-one (1:1) implementations (kernel-level threads)
每一个Thread对应一个KSE,所有线程操作自然有内核提供了——System call。
优点:【1】不会出现User-level的一个系统调用阻塞掉所有的其他Thread。【2】实现了全局调度最优~
缺点:【1】因为都是System call 自然就慢下来,why?Context switch呀。【2】对于高性能的服务器来说,上百万的Thread同时对应着kernel需要维护上百万的KSE,这回带来性能损耗的。
Linux的线程实现就是这种~
Many-to-many (M:N) implementations (two-level model)
一个进程可以关联多个KSE,多个线程可以映射到一个KSE。
优点【1】见M:1和1:1模型【2】kernel交叉的分配线程给多核CPU。
缺点【1】见M:1和1:1模型【2】Complexity!调度和信息的传递同时涉及到Kernel-level和user-level Thread了~~
Linux Implementations of POSIX Threads——POSIX线程的Linux版实现
Next Generation POSIX Threads (NGPT)
基于M:N模型的linux线程库,由IBM开发。性能介于LinuxThreads和NPTL,03年终止开发了~~
Linux Threads
Linux的一代功臣,2.6之前的kernel使用的线程库,由Xavier Leroy开发的~~大致的实现过程是:通过clone系统调用,参数CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_SIGHAND 分别用来指明共享创建者的VM虚拟内存(用户空间)、文件描述符、文件系统相关属性(umask,root directory等)、信号处理程序表和阻塞信号表和挂起信号表。kernel创建一个Manager Thread管理所有线程创建与结束等。实现内部使用real-time 实时Singal用来传递操作信息。另外,Linux Threads 与标准差异参见TLPI-33.5.1,这也是它被NPTL取代的原因。
NPTL (Native POSIX Threads Library)
Kernel2.6沿用至今,Linux Threads的继承者,有Ulrich Drepper 和 Ingo Molnar开发,这是他们的关于NPTL实现的论文草稿,他们供职于Redhat。NPTL性能远高于Linux Threads,并且更加符合Posix Thread标准。需要内核的改动支持,所以2.2与2.4的内核不支持NPTL。
NPTL实现的精要如下
【1】调用clone系统调用并指定参数(更详细的解说见ULK3e第三章):CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_SIGHAND
| CLONE_THREAD(新线程被放在和创建者相同的Thread group 线程组并且拥有和创建者相同的PID进程ID和PPID父进程ID)
| CLONE_SETTLS(Thread Local Storage简称TLS线程局部存储段,通俗的说,就是用来指明创建存储线程私有数据的地方)
| CLONE_PARENT_SETTID(把TID线程ID存放在父进程的相关结构中)
| CLONE_CHILD_CLEARTID(清楚线程设置的数据)
| CLONE_SYSVSEM(共享System V IPC 取消信号量操作)
【2】使用头两个实时信号作为内部实现通信。
NPTL与标准不一致,月有圆缺嘛,相对与Linux Threads不一致的数量,NPTL还是非常少的:
Thread之间不能共享Nice值(类似优先级,Nice值越高CPU使用时间越长)
这么多的实现,你的Linux发行版上的ThreadLibary是哪一版?Shell命令试试~~
【1】getconf GNU_LIBPTHREAD_VERSION【2】$(ldd /bin/ls | grep libc.so | awk '{print $3}') | egrep -i 'threads|nptl' 第二个命令执行如下:ldd /bin/ls | grep libc.so 输出ls这个程序中关于Libc的信息,我的Ubuntu10.10如下:libc.so.6 => /lib/libc.so.6 (0x00d25000)之后通过Pipe传给awk 这是个正则表达式 输出第三个变量,这里就是:/lib/libc.so.6 之后由$将字符串中的命令提取并执行,再送到 egrep -i 'threads|nptl' 
firo@ubuntu:~$ $(ldd /bin/ls | grep libc.so | awk '{print $3}') | egrep -i 'threads|nptl'
Native POSIX Threads Library by Ulrich Drepper et al
Linux Thread Memory Module ——Linux线程内存模型
本图来自TLPI-29.1节,版权归原作者Michael Kerrisk所有,在这里引用只为说明多线程内存模型,无商业目的~~
关于图片以及多线程栈的说明
需要特别说明下,Linux中有Main thread (一个进程有一个,就是进程最初创建的那个)和Peer-thread(可有多个)之分。Peer-thread在内存中如图所示和Shared Libraries共享库(Windows的DLL是也)以及Shared memory共享内存区一起都位于Heap 和Stack之间,但是,请注意TLPI中作者明确说明这三种之间顺序是由各自的创建时间决定的并不一定像图中那样都分出类来了,很多时候是交错的,例如,两个线程栈中间夹了个Shared memory。
Thread Stacks——线程栈
Peer-thread线程的栈大小是在创建之初决定的。Main-thread的Stack大小没有这个限制。在Linux/x86-32默认的Peer-thread大小为2M(我的Ubuntu10.10是8M),IA-64的大小为32M;我通过学长了解的淘宝服务器的内存大小为32G,以2M的栈大小计算能同时开启1.6万个线程;通过getconf得到最小栈的限制我的Ubuntu10.10显示如下:
firo@ubuntu:~$ getconf PTHREAD_STACK_MIN
16384
最小的栈为16K,那么调用pthread_attr_setstacksize把栈减小16K的话,就能同时开启高达190万个线程了~~
关于NPTL库线程栈的大小限制的更改
在TLPI中作者指出:如果RLIMIT_STACK的值不是无限时,NPTL就将她作为创建新线程的默认栈大小;
NPTL是在程序运行之前确定这个默认值的,如果要更改这个值必须要在程序main函数运行之前通过Shell命令 ulimit -s,也就是说你不能通过调用setrlimit在Run-time时设置~~但是你可以决定你要创建的线程栈的大小,通过调用pthread_attr_setstacksize。
firo@ubuntu:~$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 20
file size (blocks, -f) unlimited
pending signals (-i) 16382
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
这里显示的默认的stack size 大小为8192Kb(8M,这个值和我在程序中调用pthread_attr_getstacksize得到的结果一致)不是上文的2M,我猜想原因是不同Linux发行版不一样吧,Ubuntu更改了那么多内核属性,也不差这一个~~言归正传:
firo@ubuntu:~$ ulimit -s 16384
firo@ubuntu:~$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 20
file size (blocks, -f) unlimited
pending signals (-i) 16382
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 16384
现在设置为同getconf PTHREAD_STACK_MIN值一样了——16384byte;另外,不要忘记这个设置只对当前会话有效。
firo@ubuntu:~$ getconf PTHREAD_STACK_MIN
16384
Thread synchronization —— 线程同步
Posix提供两种线程同步模型:
Mutex:允许多个线程同步地使用共享资源。
Condition variable:一种辅助机制,当共享资源被更改了,通知其他的线程。
那么为什么要提供线程Mutex同步机制呢?
我们编写的C语言代码被as汇编器汇编成汇编指令;对于一个被多个线程访问的共享变量来说,在Thread1中的正在执行的某条汇编指令“刚”把内存中的共享变量的值读到Register寄存器中,就被cpu挂起了;CPU去执行Thread2了,而Thread2也对这个共享变量进行了操作改变了她的值——和Thread1的寄存器存的值不同了,从某种意义来说Thread1的共享变量的值是个赝品了。过了一段时间CPU又切回到了Thread1继续执行,而此时,要操作的那个寄存器中存储的值已经没有意义了——因为她已经和原来的变量一样,对于同一个变量同一时间有两个值,问题自然就来了有可能是微风吹过毫发无损,也有可能是灭顶之灾~~~所以说现在就需要英雄的出现,Mutex参上!原理非常简单,当一个线程要访问共享变量,我把它所在一个房间里;不让其他的线程访问了。等我访问完了,把房间打开,让其线程访问。这样就不会造成共享变量值不一致了。
那么为什么提供了Condition variable这个机制呢?
源于我们在应用程序的中要测试某个变量的值是否改变了的情况,生产者-消费者模型当中,消费者要用轮询poll技术(通俗点就是while循环)来检测标记产品的数量的变量是否大于0可以被消费者消费掉;通常轮询机制是非常浪费CPU资源的。所以Condition variable就应运而生了;原理格外简单:在产品超过0的情况下,主动给消费者发个短信pthread_cond_signal,我们这有货了,省着你老往这跑~~而消费者呢,发现没有货了,也不在傻乎乎的在那一遍遍的Poll测试有没有货,而是通过调用pthread_cond_wait:这个函数做三件事【1】把消费者得到的保护共享变量Mutex解锁,这样生产者才可以访问这个变量,产生产品,【2】之后调用sleep函数是消费者睡一会儿,等来短信了把消费者吵醒,【3】被吵醒,之后获得那个全局的Mutex再次锁上,之后函数返回。
为什么要有静态分配和动态分配Mutex变量两种方式呢?动态初始化和静态初始化有什么区别呢?
【1】我们先来说说什么是动态初始化和静态初始化:
Dynamically Initialization动态初始化,即Run-time运行时初始化,对于存放在Stack和Heap上的变量的初始化就是动态初始化,现在你可以想想平时遇到的那些变量属于这一类。
Statically Initializtion静态初始化,是在Run-time之前Compile、link、Load这三个阶段进行的初始化,其中static变量和全局变量的初始化就是这一类。其中大多数静态初始化都在Compile/link阶段完成了,我知道的Load阶段进行的静态初始化是定义static或全局变量分配一个特别大的空间时(比如:100M),编译器会将初始化延迟到Load阶段。
【2】再来说说变量的分配,共有3种分配方式:
Automatic memory allocation自动分配,在函数内部分配的除static变量之外的所有变量,即自动变量都属于这一类型。
Static memory allocation  静态分配,在Run-time运行之前,由编译器,链接器以及程序加载器分配的变量,全局变量和静态变量就是了,注意一定要理清静态变量和静态分配,不要搞混了。这一类变量被存在所谓的内存的静态区当中,其实,就是程序正文区和堆之间的部分,可以被细分为.rodata(常量)、.data(初始化的变量)、.bss(未初始化的变量)。这类变量的生命周期是和Process进程存在的时间一样的。
Dynamic memory allocation动态分配,在Run-time时分配,大家所熟悉的malloc、new就是了。
【3】好了,回过头来看我们的Mutex;对比下,问题不言自明,各有优缺~
静态分配(函数体之外所有变量、函数体之内的静态变量都是这样分配的)的Mutex变量用PTHREAD_MUTEX_INITIALIZER初始化后,就具有默认的属性,以及被存在静态区上了。
大家需要注意下,在函数体内部的非静态的局部Mutex变量是自动分配在栈上的,理论上也可用PTHREAD_MUTEX_INITIALIZER初始化,但这样做没有意义,因为Mutex是各个线程之间的信息交换点,局部变量显然担当不了此重任——只能被一个线程所知晓并访问。
pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);动态初始化第一个好处就是可以自己定制Mutex的属性了,另外Mutex可以被存放在Heap堆上:试想下,你在创建了一个包含Mutex的链表,你应该怎么初始化它?当然也可以动态初始化存放在栈上的Mutex。可是,反过来你却不能静态初始化存放在堆上的Mutex,why?除非你玩穿越,否则这是不可能,应为静态初始化在program运行之前,而堆是运行时的概念。
int pthread_mutex_destroy(pthread_mutex_t *mutex);在堆上分配的,自然要手动销毁了~~
相关论述参见这里:Is any difference between default and static mutex initialization? 还有这里:man 3 pthread_mutex_init
避免死锁的方法
【1】所有线程对于不同的锁使用相同顺序访问。
【2】try, and then back off策略;当线程要访问第二个Mutex资源时,用pthread_mutex_trylock测试下,如果失败就释放已拥有的第一个锁。
Mutex Types
【1】PTHREAD_MUTEX_NORMAL:不侦测死锁是否发生
一个线程对已经被自己上锁的Mutex,再次上锁将产生Deadlock。解锁一个被别的线程锁住的Muex和未上锁的Mutex的行为都是未定以的。
【2】PTHREAD_MUTEX_ERRORCHECK:提供错误告知
一个线程对已经被自己上锁的Mutex,再次上锁将返回一个错误。解锁一个被别的线程锁住的Muex和未上锁的Mutex的将返回一个错误。
【3】PTHREAD_MUTEX_RECURSIVE:允许递归上锁
一个线程对已经被自己上锁的Mutex,再次上锁成功返回。理所当然的需要等量的解锁操作。解锁一个被别的线程锁住的Muex和未上锁的Mutex的将返回一个错误。
【4】PTHREAD_MUTEX_DEFAULT:Linux上等价于PTHREAD_MUTEX_NORMAL
/usr/include/pthread.h 定义:PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
Thread Safety——线程安全
Non-thread-safe functions线程不安全函数
我们首先看下CS:APP中线程安全函数的定义:一个函数被认为线程安全,当且仅当被多个并发线程同时反复调用,仍会产生正确的结果。
CS:APP富有深刻洞察力的给出了四类不是线程安全的函数,具体论述见CS:APP2e第12章:
【1】Failing to protect shared variables不保护共享变量的函数。
【2】Relying on state across multiple function invocations需要调用其他函数的函数。
【3】Returning a pointer to a static variable返回值是静态(分配)变量;我觉的这一类情况中函数的返回值一般都是static类型的,其实返回值是全局变量也属于这一类,所以我加了“(分配)”做解释。
【4】Calling thread-unsafe functions调用了线程不安全函数的函数。
CS:APP关于Reentrant function的描述:可重入函数属于线程安全函数,特别之处在于:他们不引用Shared Data共享数据。 Explicitly reentrant显式可重入:函数参数为传值传递,函数所使用变量只用自动分配的栈变量。Implicity reentrant隐式可重入:参数含指针,但小心处理就可。
Per-thread Storage——线程数据存储
One-Time Initialization一生就一次
TLPI中说明了pthread_once这个函数存在的主要原因是:早期的Pthread库,无法静态初始化Mutex变量;作为替代,使用pthread_mutex_init动态初始化。那么一个线程例程函数(就是线程执行的函数)中调用了一个需要初始化Mutex的库函数;因为多线程嘛,每个线程如果没有什么机制限制的化,都会初始化Mutex一次。Man手册中指出:对一个已初始化的变量初始化的结果是不确定的!况且多次初始化会出现:一个线程初始化后更改了共享变量的值后,另一个线程又初始化了一次将上个线程的工作抹杀掉了。所以pthread_once就是实现这个功能:保证多个线程只对这个Mutex初始化一次,怎么做到的呢?虽然后来支持了静态初始化Mutex变量,但pthread_once仍然留了下来,没有被标准剔除,原因如下;当然,还有其他的应用原因。
Thread-Specific Data每个线程特定的私有数据
使用Thread-Specific Data【TSD】这个技术可以使那些已存在的Non-thread-safe线程不安全的函数在不改变接口(重点!)的前提下变成Thread-seafe线程安全(CS:APP介绍了其他几种线程安全化的技术),使每个线程都能使用自己私有的数据,不干扰到彼此(Threads)。要理解这个技术具体的实现,你需要先来理清几点重要的概念:【1】Thread-routine线程例程函数:新创建的Peer-thread线程在整个生命周期内执行的函数,类似于大家熟悉的Main-thread的main函数。【2】多个线程可以同时执行相同的Thread-routine线程例程函数,也可以同时执行不同的线程例程函数。【3】(尤为重要)Pthread-key与Thread-routine线程例程函数是一一对应的关系,也就是说Pthread-key键是用来区别不同的线程例程函数的~~【4】一个线程可以指定多个私有的数据存储区。【5】这个特定于线程例程函数的Key只能被pthread_key_create创建一次,所以pthread_once,参上!【6】NPTL线程库在为我们在每一个进程内都维护两个数据结构:first,全局Pthread-key数组,用来记录进程内所有键的使用情况;second,对于进程内每一个被使用的Pthread-key键,都有一个数组用来存储所有使用这个键(实际上使用的是那个键对应的线程例程函数:-))的线程的所有(一个线程可以有多个存储区:同一个线程使用相同的Key和不同的存储区多次调用pthread_setspecific)私有数据存储区的地址。【7】pthread_getspecific函数的查找过程:参数Key--->哪一个Thread--->哪一个数据存储区--->Address;好的,我们现在回到开始,要使一个一个线程不安全的函数编程一个线程安全的函数,常用的一个技术就是重写这个函数,又因为这一类线程不安全的函数常常是因为使用了静态的变量作为函数返回值,造成多个线程同时调用这个函数会彼此覆盖返回值;而重写这个函数一般是改变函数接口,增加由调用指定的数据返回值的存储位置,来避免覆盖发生;你也许回看到一些以_r作为后缀的函数,他们多半是使用这种改变接口的技术达到线程安全的目的。所以在同样重写的情况,我们应用TSD技术就可以不改变API的接口;我想这是有划时代意义的,至少对于那些老的程序来说,要知道他们什么都们改变就达到Tread-safe的目的了:-)
这是每个进程内Pthread-key键的限制个数:
firo@ubuntu:~$ getconf PTHREAD_KEYS_MAX
1024 
Thread-Local Storage线程局部的私有数据
Thread Cancellation——取消线程
Thread and Signal——线程与线号
Origin起源——一切的答案都在这里
故事的发生,追溯到40年前——最初Signal信号机制是为Process进程模型量身打造的;可是,在20年前的某个夜黑风高的晚上(在Silently Hill这个地方)Pthread出现了,伴随而来的是代沟——为了既保持信号原有针对进程的语义(定义)同时又要保证信号与多线程模型和谐共处。而要想透彻的了解现在的信号与多线程,你需要追根溯源(回到寂静岭),理解清下面几个概念:
保持原有Signal信号机制是针对进程语义:
信号的deliver递送(产生)、Signal handler信号处理器的dispositions部署(处理)、信号的产生的结果是针对进程的(结果);
【1】也就是说Signal handler信号处理器是配置给一个进程的,进程内的多个线程是公用这一个Signal handler的;
【2】也就是说,信号是deliver递送给进程的,进程内的多个线程是共享并处里所有这些信号的;
【3】也就是说,当一个线程处理一个signal的结果是Stop或Terminate,那么整个进程就Stop或Terminate。
为了与线程模型相适应,信号针对线程的属性如下:
【0】一个进程内的所有产生的信号分为不相交的两个集合:针对进程的——所有线程共享;针对单个线程的——每个线程自己私有,如下:
当在某个线程的Context上下文的硬件指令产生的信号SIGBUS, SIGFPE, SIGILL, and SIGSEGV;
当线程去写一个Broken的Pipe管道,产生的SIGPIPE;
当pthread_kill() or pthread_sigqueue()发送给某个特定线程;
【1】每个线程有自己独立的Signal  Mask信号掩码集,也就是说Main-thread和每个Peer-thread都可以自主的决定阻塞哪个信号。这样就是我们在编程时,独立创建一个线程处理所有的信号成为可能——其他线程阻塞所有信号。
【2】一个信号被递送给包含多个线程的进程时,kernel随机的从没有阻塞该信号的线程中选择一个,来处理这个信号。
firo_baidu
关注
关注
点赞
收藏
打赏
评论
Linux Concurrent Programming —— Thread【Beta1-Updating】
Linux Concurrent Programming —— Thread——by firo 2011.4.26
复制链接
扫一扫
专栏目录
linux下的并发编程详解
Leon的博客
04-06
733
使用应用级并发的应用程序称为并发程序(concurrent program)。现代操作系统提供3种基本的构造并发程序的方法:进程、I/O多路复用和线程。下面将分别予以讨论。
1. 基于进程的并发编程
我们可以利用熟悉的fork、execve及waitpid函数来开发基于进程的并发编程。下面以构造并发服务器为例,在服务器程序中,父进程接受客户端的连接请求,然后创建一个新的子进程为每一...
互联网高并发架构技术实践
weixin_33971977的博客
06-01
257
一、什么是高并发
高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。
高并发相关常用的一些指标有响应时间(Response Time),吞吐量(Throughput),每秒查询率QPS(Query Per Second),并发用户数等。
响应时间:系统对请求做出响应的时间。例如系统处理一个HTT...
参与评论
您还未登录,请先
登录
后发表或查看评论
Concurrent Programming in Java™: Design Principles and Patterns 2nd
02-14
This book shows readers how to use the Java platform's threading model moreprecisely by helping them to understand the patterns and tradeoffs associated withconcurrent programming
linux下高并发的解决方案
june_young_fan的博客
03-24
4972
Linux下高并发socket最大连接数所受的各种限制
在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每个TCP连接都要创建一个socket句柄,每个socket句柄同时也是一个文件句柄)。可使用ulimit命令查看系统允许当前用户进程打开的文件数限制:
[speng@as4 ...
functional programming
leon3389的专栏
05-22
7099
Why Functional Programming?Functional programs contain no assignment statements, so variables, once given a value, never change. More generally, functional programs contain no side-effects at all. A ...
Oracle VM VirtualBox R ? Programming Guide and Reference
yangjia_cheng的博客
03-23
3487
Oracle VMVirtualBoxR ?Programming Guide andReferenceVersion 5.2.8c ? 2004-2018 Oracle Corporationhttp://www.virtualbox.orgContents1 Introduction 211.1 Modularity: the building blocks of VirtualBox . ....
libev-4.0.3 manual
fei的专栏
12-14
1388
=head1 NAME
libev - a high performance full-featured event loop written in C
=head1 SYNOPSIS
#include
=head2 EXAMPLE PROGRAM
// a single header file is required
#in
CISCO技术(1.7万)
热门推荐
08-09
6万+
0 base|以零为基底\r\n
0 disturbed zero output signal|干扰0输出信号\r\n
0parallel communication cable|平行通讯传输缆线\r\n
1 binary operation|二进制运算\r\n
1 di
Xen and the Art of Virtualization
MincludeA的专栏
06-09
2884
<br />Xen and the Art of Virtualization
Paul Barham, Boris Dragovic, Keir Fraser, Steven Hand, Tim Harris,
Alex Ho, Rolf Neugebauery, Ian Pratt, Andrew Wareld
University of Cambridge Computer Laboratory
15 JJ Thomson Avenue, Cambridge, UK, CB3 0FD
Upgrading to Indy 10
笨笨的专栏
08-23
3068
1148Upgrading to Indy 10Chad HowerAtozed SoftwareAbstract: This session covers the changes made to Indy 10 and how to quickly port existing code. It also covers the advantages of Indy 10 and why you s
Golang优秀开源项目汇总, 10大流行Go语言开源项目, golang 开源项目全集(golang/go/wiki/Projects), GitHub上优秀的Go开源项目...
weixin_34245082的博客
05-08
4287
Golang优秀开源项目汇总(持续更新。。。)我把这个汇总放在github上了, 后面更新也会在github上更新。 https://github.com/hackstoic/golang-open-source-projects 。 欢迎fork, star , watch, 提issue。
资料参考来源:http://studygolang.com/projects
监控...
Awesome Go精选的Go框架,库和软件的精选清单.A curated list of awesome Go frameworks, libraries and software...
浩秦的博客
10-22
1680
Awesome Go
financial support to Awesome Go
A curated list of awesome Go frameworks, libraries and software. Inspired byawesome-python.
Contributing
Please take a quick gander at th...
Go 语言相关的优秀框架,库及软件列表
aa110212312的博客
09-11
1465
If you see a package or project here that is no longer maintained or is not a good fit, please submit a pull request to improve this file. Thank you!
Contents
Awesome Go
Audio and Music...
go语言资源大全
yang889999888的博客
07-19
6081
转载地址:https://github.com/avelino/awesome-go
Contents
Awesome Go
Audio & MusicAuthentication & OAuthCommand LineConfigurationContinuous IntegrationCSS PreprocessorsData StructuresDatabaseData
高负载高并发网站架构分析
Steven_ssm的博客
08-28
2万+
由于自己正在做一个高性能大用户量的论坛程序,对高性能高并发服务器架构比较感兴趣,于是在网上收集了不少这方面的资料和大家分享。希望能和大家交流
msn: defender_ios@hotmail.com
———————————————————————————————————————
 初创网站与开源软件 6
 谈谈大型高负载网站服务器的优化心得! 8
 Lighttpd+S
机器学习(ML)、深度学习(DL)和图像处理(opencv)专用英语词典
wyx100的专栏
07-07
1万+
机器学习(ML)、深度学习(DL)和图像处理(opencv)专用英语词典
百度翻译
http://fanyi.baidu.com/
AAN (Active Appearance Model)主动外观模型
Adam(adaptive moment estimation,适应性矩估计),Adam是一种可以替代传统随机梯度下降过程的一阶优化算法,它能基于训练数据迭代地更新神经网络权重。Ad...
nRF5_SDK_13.0.0_04a0bfd
好习惯成就伟大
05-18
3167
nRF5 SDK v13.0.0------------------------Release Date: Week 11, 2017Highlights:- Implemented a new license scheme for the SDK distribution. See the documentation folder for details.- Updated the Blue...
2000个软件开发领域的高频特殊词及精选例句(一)
03-26
2352
superword是一个Java实现的英文单词分析软件,主要研究英语单词音近形似转化规律、前缀后缀规律、词之间的相似性规律等等。
1、单词 hadoop 的匹配文本:
Subash D'Souza is a professional software developer with strong expertise in crunching big data using Hado...
Enhancing the Scalability of Memcached
weixin_33936401的博客
05-11
139
原文地址: https://software.intel.com/en-us/articles/enhancing-the-scalability-of-memcached-0
1 Introduction - Memcached and Web Services
Memcached is a Key-Value cache used by cloud and web service deli...
mfs 分布式文件系统
hardccyy的专栏
06-03
2119
mfs权威指南(moosefs)分布式文件系统一站式解决方案(部署,性能测试)不断更新
http://bbs.chinaunix.net/thread-1644309-1-1.html
1. 我在性能测试中间遇到些问题,因为我时间有限,所以希望大家一起来测试解决,群策群力。有什么问题请大家及时指出来,因为我也处在一个不断摸索的阶段。
“相关推荐”对你有帮助么?
非常没帮助
没帮助
一般
有帮助
非常有帮助
提交
©️2022 CSDN
皮肤主题:大白
设计师:CSDN官方博客
返回首页
firo_baidu
CSDN认证博客专家
CSDN认证企业博客
码龄12年
暂无认证
19
原创
96万+
周排名
154万+
总排名
8万+
访问
等级
1098
积分
69
粉丝
获赞
34
评论
收藏
私信
关注
热门文章
Computer science —— 书单
21242
yaml-cpp —— C++ 项目配置工具入门
10623
Linux——epoll
5775
Linux——信号驱动IO
5532
Ragel——基于有限状态机用于产生源码的编译器
5070
分类专栏
Algorithms
1篇
Essential Knowledge
ETC
4篇
Linux
7篇
Cloud computing
1篇
最新评论
Ragel——基于有限状态机用于产生源码的编译器
技术菌的blog:
我很欣赏博主这想法。。我当初咋没想到呢?大一接触c语言,概念真难懂,要是有程序帮我写程序该多好啊
Ragel——基于有限状态机用于产生源码的编译器
deniece:
具体怎么使用呢,到官网下载之后。
Ragel——基于有限状态机用于产生源码的编译器
kangear:
这么厉害?
您愿意向朋友推荐“博客详情页”吗?
强烈不推荐
不推荐
一般般
推荐
强烈推荐
提交
最新文章
Cloud computing —— 云计算
Ragel——基于有限状态机用于产生源码的编译器
yaml-cpp —— C++ 项目配置工具入门
2011年19篇
2010年4篇
目录
目录
分类专栏
Algorithms
1篇
Essential Knowledge
ETC
4篇
Linux
7篇
Cloud computing
1篇
目录
评论
被折叠的 条评论
为什么被折叠?
到【灌水乐园】发言
查看更多评论
打赏作者
firo_baidu
你的鼓励将是我创作的最大动力
¥2
¥4
¥6
¥10
¥20
输入1-500的整数
余额支付
(余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付
您的余额不足,请更换扫码支付或充值
打赏作者
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额
抵扣说明:
1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。
余额充值