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)

阅读剩余
THE END