这里的进程锁与线程锁、互斥量、读写锁和自旋锁不同,它是通过记录一个PID文件,避免两个进程同时运行的文件锁。进程锁的作用之一就是可以协调进程的运行,例如crontab使用进程锁解决冲突提到,使用crontab限定每一分钟执行一个任务,但这个进程运行时间可能超过一分钟,如果不用进程锁解决冲突的话两个进程一起执行就会有问题。
关于这本书本书受理解Unix进程启发而作,用极简的篇幅深入学习进程知识。理解Linux进程用Go重写了所有示例程序,通过循序渐进的方法介绍Linux进程的工作原理和一切你所需要知道的概念。本书适合所有Linux程序员阅读。在线阅读,PDF下载。三位好朋友阅读前介绍三位即将与大家打交道的小伙伴:Linux、Go和Docker。
极简的篇幅深入学习进程知识
在Java中String类的使用的频率可谓相当高。它是Java语言中的核心类,在java.lang包下,主要用于字符串的比较、查找、拼接等等操作。如果要深入理解一个类,最好的方法就是看看源码:
深入理解 JavaScript 教程,内容来源包括了原创,翻译,转载,整理等各类型文章,是作者根据实际经验的一个整合。本教程对 JavaScript 语言的函数、原型、闭包、面向对象等关键知识点做了详细介绍;根据实际开发需要,引入设计模式,让读者能够由浅入深地掌握这门语言的特点,解决实际开发过程中的问题。适用人群本教程为 JavaScript 中高级教程,是初学者进阶的理想教程。
深入 理解 JavaScript
在考虑如何对业务模型进行抽象从而建立领域模型之前,必须解决业务与产品、开发之间“沟通”的问题。如何让业务人员和开发人员顺畅沟通,在业务流程设计中不遗漏成败攸关的业务场景?如何才能让业务沟通的过程顺畅过渡到架构设计、编码乃至测试?阿里巴巴技术专家李建结合团队的实际案例,分享了他们在使用 Event Storming(事件风暴) 进行领域建模时的经验、收获和思考。
Java内存区域是指 JVM运行时将数据分区域存储 ,简单的说就是不同的数据放在不同的地方。通常又叫 运行时数据区域。
最后一章列举本文参考过的书籍和项目,欢迎大家补充和讨论更多有关进程的知识。
Cgroups全称Control Groups,是Linux内核用于资源隔离的技术。目前Cgroups可以控制CPU、内存、磁盘访问。使用Cgroups是在Linux 2.6.24合并到内核的,不过项目在不断完善,3.8内核加入了对内存的控制(kmemcg)。要使用Cgroups非常简单,阅读前建议看sysadmincasts的视频,https://sysadmincasts.com/episodes/14-introduction-to-linux-control-groups-cgroups。
Epoll是poll的改进版,更加高效,能同时处理大量文件描述符,跟高并发有关,Nginx就是充分利用了epoll的特性。讲这些没用,我们先了解poll是什么。PollPoll本质上是Linux系统调用,其接口为int poll(struct pollfd *fds,nfds_t nfds, int timeout),作用是监控资源是否可用。
我们要想启动一个进程,需要操作系统的调用(system call)。实际上操作系统和普通进程是运行在不同空间上的,操作系统进程运行在内核态(todo: kernel space),开发者运行的进程运行在用户态(todo: user space),这样有效规避了用户程序破坏系统的可能。如果用户态进程想执行内核态的操作,只能通过系统调用了。
我们知道信号是进程间通信的其中一种方法,当然也可以是内核给进程发送的消息,注意信息只是告诉进程发生了什么事件,而不会传递任何数据。这是进程这个概念设计时就考虑到的了,因为我们希望控制进程,就像一个小孩我们想他按我们的想法做,前提就是他能够接受信号并且理解信号的含义。
IPC全称Interprocess Communication,指进程间协作的各种方法,当然包括共享内存,信号量或Socket等。管道(Pipe)管道是进程间通信最简单的方式,任何进程的标准输出都可以作为其他进程的输入。信号(Signal)下面马上会介绍。消息队列(Message)和传统消息队列类似,但是在内核实现的。共享内存(Shared Memory)后面也会有更详细的介绍。
当一个进程完成它的工作终止之后,它的父进程需要调用wait()或者waitpid()系统调用取得子进程的终止状态。一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。理解了孤儿进程和僵尸进程,我们临时加了守护进程这一小节,守护进程就是后台进程吗?
本章开始时演示了Hello World程序,其实已经创建了新的进程,通过Bash或者zsh这些Shell很容易创建新的进程,但Shell本身是怎么实现的呢?我们又能不能用Go实现类似Shell的功能呢?系统调用原来这一切都是操作系统给我们做好的,然后暴露了使用的API接口,这就是系统调用。
在Linux中“一切皆文件”,进程的一切运行信息(占用CPU、内存等)都可以在文件系统找到,例如看一下PID为1的进程信息。
任何进程退出时,都会留下退出码,操作系统根据退出码可以知道进程是否正常运行。退出码是0到255的整数,通常0表示正常退出,其他数字表示不同的错误。示例程序package mainfunc main() { panic("Call panic()")}运行结果root@fa13d0439d7a:/go/src# go run exit_code.gopanic: Call panic()goroutine 16 [running]:runtime.
根据进程的定义,我们知道进程是代码运行的实体,而进程有可能是正在运行的,也可能是已经停止的,这就是进程的状态。网上有人总结进程一共5种状态,也有总结是8种,究竟应该怎么算呢,最好的方法还是看Linux源码。进程状态的定义在fs/proc/array.c文件中。/** The task state array is a strange "bitmap" of* reasons to sleep.
前面提到多进程的并行可以提高并发度,那么进程是越多越好?一般遇到这种问题都回答不是,事实上,很多大型项目都不会同时开太多进程。下面以支持100K并发量的Nginx服务器为例。举个例子: NginxNginx是一个高性能、高并发的Web服务器,也就是说它可以同时处理超过10万个HTTP请求,而它建议的启动的进程数不要超过CPU个数,为什么呢?
关注时代Java