linux 0进程,linux最好用的系统
Linux下0号进程的前世今生
Linux中的特殊进程世界里,0号进程有着不平凡的旅程。首先,让我们探寻idle进程的起源。当内核初始化开始,系统生成的第一个进程,即pid=0的idle进程,其存在并非通过fork(),而是系统固有的产物。在SMP系统中,每个处理器都有独立的运行队列,每个队列上都驻留着一个idle进程,数量与处理器数量一致。
idle进程的标志性存在是init_task,它是所有进程和线程task_struct的原型,由内核静态定义并命名为init_task。它的进程描述符init_task_desc通过INIT_TASK宏初始化,其comm字段为swapper。在进程生命周期中,init_task先创建kernel_init进程,然后自己退化为cpu_idle进程,负责在无其他进程时占用CPU资源。
init_task的内存管理复杂,它使用init_thread_union作为堆栈空间,并与thread_info共享内存。进程堆栈和虚拟地址空间的初始化同样由内核控制,如arm体系结构下的定义。随着系统启动,rest_init函数启动了进程创建的进程,包括init进程(PID=1)和kthread进程(PID=2)。
在创建了init进程后,0号进程(pid=0)通过调用cpu_idle(),进入idle进程状态,init_task随之变成idle。在这个过程中,init_task被置于idle调度类,其行为主要在cpu_idle_loop中,通过检查need_resched来节能,或者使用hlt指令进入暂停状态。
在调度策略上,当rt和cfs调度器没有任务时,idle进程才有机会运行。idle进程的调度是由cfs公平调度器和idle_sched_class协作完成的。在系统空闲时,idle进程会通过pick_next_task函数被调度。
总结来说,0号进程,无论是作为init_task还是idle,都是Linux进程结构的基石。它通过一系列的初始化和演变,不仅启动了系统进程,还为后续的进程创建和调度奠定了基础。在系统中,它既是所有进程的祖先,也是CPU空闲时的守护者,维护着系统的稳定运行。
如何查看Linux下进程的IO活动状况 00 Hey,Linux
前段时间,几台测试服务器的Web应用响应速度非常慢,系统负载也比较高,> 10,但CPU和内存却很闲,于是怀疑是磁盘的性能瓶颈,通过vmstat和iostat看到IO的读写量非常大,尤其是用iostat-x 1命令可以很直观的看到IO的使用率一直在100%。
但究竟是什么进程导致的高IO呢,由于每台服务器上都有JBoss和MySQL的存在,JBoss会不停的产生很多小的数据文件和生成文本数据库的数据,而MySQL则会不停的从Master同步新的数据。因此我们怀疑是这两个进程导致的高IO,通过停止了JBoss和MySQL之后,IO立刻降为0%.但我们还是不能确定谁是主因,于是寻找可以查看特定进程IO的方法。
最后,找到了两个方法可以查看进程IO的活动状况。
1.第一个方法是通过一个python脚本来实现。
方法是将以下内容另存为一个叫io.py的脚本中,然后直接以root身份执行脚本,就可以看到如下图所示的信息(由于我们已经通过升级到SSD硬盘解决了MySQL的IO问题,所以不能提供关于MySQL的截图了),其中出现次数最多,数据最大的进程,就是导致高IO的主因。不过比较遗憾的是这个脚本并不能显示进程在每一秒的准确的IO读写。
# vim io.py
# chmod+x io.py
#./io.py
#!/usr/bin/python
# Monitoring per-process disk I/O activity
# written by
import sys, os, time, signal, re
class DiskIO:
def __init__(self, pname=None, pid=None, reads=0, writes=0):
self.pname= pname
self.pid= pid
self.reads= 0
self.writes= 0
def main():
argc= len(sys.argv)
if argc!= 1:
print"usage:./iotop"
sys.exit(0)
if os.getuid()!= 0:
print"must be run as root"
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
os.system('echo 1>/proc/sys/vm/block_dump')
print"TASK PID READ WRITE"
while True:
os.system('dmesg-c>/tmp/diskio.log')
l= []
f= open('/tmp/diskio.log','r')
line= f.readline()
while line:
m= re.match(\
'^(\S+)\((\d+)\):(READ|WRITE) block(\d+) on(\S+)', line)
if m!= None:
if not l:
l.append(DiskIO(m.group(1), m.group(2)))
line= f.readline()
continue
found= False
for item in l:
if item.pid== m.group(2):
found= True
if m.group(3)=="READ":
item.reads= item.reads+ 1
elif m.group(3)=="WRITE":
item.writes= item.writes+ 1
if not found:
l.append(DiskIO(m.group(1), m.group(2)))
line= f.readline()
time.sleep(1)
for item in l:
print"%-10s%10s%10d%10d"%\
(item.pname, item.pid, item.reads, item.writes)
def signal_handler(signal, frame):
os.system('echo 0>/proc/sys/vm/block_dump')
sys.exit(0)
if __name__=="__main__":
main()
2.另一个方法是将Linux的内核升级到>=2.6.20,然后安装一个iotop软件来实现。
不过这种改动并不适用于生产环境,因为在RHEL5.6和5.7上,内核都在 2.6.20以下。但是它所显示的结果是非常准确的,所以对于新上线的机器以及测试环境,非常值得一试,具体方法如下:
下载和升级新内核(>=2.6.20),编译时打开 TASK_DELAY_ACCT和 TASK_IO_ACCOUNTING选项。
解压内核后进入配置界面:
# wget
# tar jxvf linux-2.6.39.tar.gz
# mv linux-2.6.39/usr/src/
# cd/usr/src/linux-2.6.39
# make oldconfig//使用make oldconfig可以继承老的kernel的配置,为自己的配置省去很多麻烦。
# make menuconfig
把General setup- Enable per-task storage I/O accounting这个选项选上。
# vim.config
将#CONFIG_SYSFS_DEPRECATED_V2 is not set的注释去掉的,将其改为y,即修改为CONFIG_SYSFS_DEPRECATED_V2=y。
保存内核后编译内核:
# make
# make modules
# make modules_install
# make install
修改默认以新的内核启动:
# vi/boot/grub/grub.conf
default=0
将新的内核配置文件复制到/boot目录:
# cp/usr/src/linux-2.6.39/.config/boot/config-2.6.39
重启服务器:
# reboot
# uname–r
2.6.39
重启完成后确认内核版本是否正确。
源码安装iotop所需的Python 2.7.2(>= 2.5):
# wget
# tar xzvf Python-2.7.2.tgz
# cd Python-2.7.2
#./configure
# make; make install
下载并安装iotop:
# wget
# tar-xjvf iotop-0.4.4.tar.bz2
# cd iotop-0.4.4
# python setup.py build
# python setup.py install
然后就可以使用iotop看到如下图所示的信息:
Linux内核中进程0的主要任务是什么
总结一下有如下几个要点:
1.进程0是所有其他进程的祖先,也称作idle进程或swapper进程.
2.进程0是在系统初始化时由kernel自身从无到有创建.
3.进程0的数据成员大部分是静态定义的,即由预先定义好的INIT_TASK, INIT_MM等宏初始化.
进程0的描述符init_task定义在arch/arm/kernel/init_task.c,由INIT_TASK宏初始化。 init_mm等结构体定义在include/linux/init_task.h内,为init_task成员的初始值,分别由对应的初始化宏如INIT_MM等初始化
Process 1
进程0最终会通过调用kernel_thread创建一个内核线程去执行init函数,这个新创建的内核线程即Process 1(这时还是共享着内核线程0的资源属性如地址空间等)。init函数继续完成剩余的内核初始化,并在函数的最后调用execve系统调用装入用户空间的可执行程序/sbin/init,这时进程1就拥有了自己的属性资源,成为一个普通进程(init进程)。至此,内核初始化和启动过程结束。下面就进入了用户空间的初始化,最后运行shell登陆界面。(注:Init进程一直存活,因为它创建和监控在操作系统外层执行的所有进程的活动。)
——————
这段对进程0的描述引用自《Understanding The Linux Kernel- Third Edtion》
The ancestor of all processes, called process 0, the idle process, or, for historical reasons, the swapper process, is a kernel thread created from scratch during the initialization phase of Linux. This ancestor process uses the following statically allocated data structures(data structures for all other processes are dynamically allocated)