Skip to main content

Operating System- Process and Thread Review

回顾总结
process and thread

process是操作系统调度的基本单位,一个程序可以理解为一个进程。
thread是process的子process,是process调度的基本单位。
  从调度角度理解process和thread
  我们知道操作系统调度的时候是以process为单位的,即当我们的程序是单thread的process时,那在这个process获得cpu的时间片时,这个thread能够获得全部的这个时间片。在内核中,我们维护着一个process的table,来记录每个process的基本信息,根据不同的调度方式来使用这个信息或者不使用。
  当一个process拥有多个thread时,如何调度thread呢?

  •  当thread为内核态thread时。
  •  当thread为用户态thread时。
  • 混合实现不做讨论

  两种情况则有不同的调度方式。当为内核态的thread时,即此时的thread可以称之为轻量级的process,这个时候内核来维护一个thread table和process table相似。同时操作系统来调度thread,就像调度process一样。当为用户态的线程时,那么操作系统感受不到多个thread的存在,因为此时操作系统调度的对象是process,一个process中有多少个thread他不关心,所以当一个process得到CPU时间片后,他会自己来调度thread。
  了解他们两个基本工作方式后,应该清楚这两种线程的主要区别:调度者是谁?各个的优缺点是什么?在JAVA中使用的哪种thread?Golang中goroutine是如何对应到我们操作系统的调度单位上去的?

  • 调度者。 内核态的thread:内核。 用户态的thread:process
  • 内核态thread的优点:在单个thread进行syscall而阻塞 时(一个线程不可以即运行代码,又能进行syscall),操作系统可以切换到同process中或者其他process下一个可以执行的thread,而不必阻塞,然而用户态的thread在进行syscall时,整个process下的thread都会阻塞。用户态的thread优点是在进行thread切换时消耗非常小,因为他不需要像内核态的thread那样需要陷入一次内核。
  • Java中根据不同JVM而视情况决定,一般来说是1:1的模型,即JVM中的线程和操作系统的thread一一对应。理解这一点我们可以清楚,java的thread也不是可以无限制的增长(内核中thread table的大小是有限制的),而且创建一个thread的消耗也很大。
  • Gorouting中的有一个参数GOMAXPROCS (The GOMAXPROCS variable limits the number of operating system threads that can execute user-level Go code simultaneously)   也就是这些goroutine是对于thread是N:1的模型,因为goroutine是由一个叫做context的结构来管理,context挂载一个thread,一次次来把当前可运行的goroutine压栈进行运行。当一个goroutine进行syscall时,当前context就只保留这么一个goroutine,scheduler来保证有下一个或者说有足够context来执行其他goroutine。详见:go-scheduler 



Comments

Popular posts from this blog

学习服务器配置之路~~

第一个常见的小问题:MySQL安装 os : fedora 20 mysql: mysql-server(5.5) 所有假设你的系统是没有经过特殊配置的。 1: yum install mysql-server 2: mysql 报错:socket连接不上 3: service mysqld start   注意这步是 mysqld 不是mysql 这样就解决。网上的方法好像有点麻烦。 第二个小问题:解压一些文件(.tar.gz)时报错 http://itsfoss.com/how-solve-stdin-gzip-format/ 上面介绍的很清楚,总之要先确认你下载的文件类型。 第三个小问题。配置tomcat服务器 主要问题是比如我的域名是 cqupt.me 而你tomcat服务器的项目在/webapps/{your projectname} 这时你很蛋疼的要 cqupt.me:8080/{your projectname}/index.html。 如果要cqupt.me就可以完成。这样配置: 都是在tomcat下/conf/server.xml 第一步端口。简单 不废话 第二部。 <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false"> </Host> 在标签中间插入: <Context path=""  docBase="xbwl"  debug="0" reloadable="true"/> docBase="xbwl" xbwl 即为指定的项目。即({your projectname}_ 完整如下: <Host name="localhost" appBase="webapps" ...

Golang http server performance tuning practice (Golang HTTP服务器性能调优实践)

  Golang 1.8后本身自带了pprof的这个神器,可以帮助我们很方便的对服务做一个比较全面的profile。对于一个Golang的程序,可以从多个方面进行profile,比如memory和CPU两个最基本的指标,也是我们最关注的,同时对特有的goroutine也有运行状况profile。关于golang profiling本身就不做过多的说明,可以从 官方博客 中了解到详细的过程。   Profile的环境 Ubuntu 14.04.4 LTS (GNU/Linux 3.19.0-25-generic x86_64) go version go1.9.2 linux/amd64  profile的为一个elassticsearch数据导入接口,承担接受上游数据,根据元数据信息写入相应的es索引中。目前的状况是平均每秒是1.3Million的Doc数量。   在增加了profile后,从CPU层面发现几个问题。 runtime mallocgc 占用了17.96%的CPU。 SVG部分图如下 通过SVG图,可以看到调用链为: ioutil.ReadAll -> buffer.ReadFrom -> makeSlice -> malloc.go  然后进入ReadAll的源码。 readAll()方法 func readAll(r io.Reader, capacity int64) (b []byte, err error) { buf := bytes . NewBuffer ( make ([] byte , 0 , capacity )) // If the buffer overflows, we will get bytes.ErrTooLarge. // Return that as an error. Any other panic remains.   defer func() { e := recover () if e == nil { return } if panicErr , ok := e .( error ) ; ok && p...

Python 使用socket实现ftp 客服端

之前先了解ftp协议,然后解释代码 连接到ftp服务器,得到一个socket(这是一个连接到ftp命令端口socket) 发送必要request 第一步 Connect到服务器后,ftp_socket.recv(1024) 到服务器的欢迎消息(1 中的socket),不要问为什么,ftp协议规定的,应该是。 *注意的是,后面ftp_socket每一次的请求后,都要recv一次,不管你是否全部接受到了都要recv一次,不然可能后面接受不到一些消息。个人觉着这可能是ftp协议的规定:每一次request,都会给client一个response。如果 client没有接受这个response,那么下次的request不会被服务器接受,所以client的recv就会卡住! 第二步就像代码中 直到 #LIST 都是用的命令端口。 而使用数据端口时,就是用命令端口   ftp_socket.send("PASV \r\n")     new_port = ftp_socket.recv(1024)      使用命令 PASV 请求一个动态的数据端口。 解释 我理解的动态数据端口: 即你每一次请求到一个数据端口后,你只能使用一次。比如: [ INFO] 2014-11-29 22:25:44,682 [admin] [127.0.0.1] SENT: 227 Entering Passive Mode (127,0,0,1,204,82)    这是ftp服务器端发送的请求(apache ftpserver),明显括号中是你的ip(我的是本机),然后两个数字。通过查询,你要请求的数据端口:(a,b,c,d,x,y)  new_port  = x*250+y 剩下的部分就很简单了。在代码中再有点解释(后面附server端log) 最后还应该用发送一个quit命令,告诉server 我的请求完毕了。这里忘了。 一点补充:看到server端log可以发现,服务器每一次的SEND  我们都应该recv一次 #download a folder's files  import socket class ParseUrl()...