转载请注明出处,http://blog.csdn.net/suool/article/details/38406211,谢谢。

Linux进程存储结构和进程结构

可运行文件结构

例如以下图:

能够看出,此ELF可运行文件存储时(没有调入内存)分为代码区、数据区和未出花数据区三部分。

代码区:存放cpu的运行的机器指令。

数据区:包括程序中的已经初始化的静态变量,以及已经初始化的全局变量。

未初始化数据区:存入的是未初始化的全局变量和未初始化的静态变量。

如今在上面的程序代码中添加一个int的静态变量,结果例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc3Vvb2w=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

代码部分添加了4个字节。是int的大小。

进程结构

假设将一个ELF格式可执行文件载入到内存中执行,则将演变成一个或多个进程。进程是Linux事务管理的基本单元,全部的进程均拥有独立的环境和资源。

下图展示一个ELF可运行文件的存储结构和Linux进程基本结构的对比:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc3Vvb2w=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

上图仅给出了一个进程的在内存中申请的代码区、初始化数据区、未初始化数据区、堆区、栈区五个部分。

为了更好的管理linux所訪问的资源,系统定义了进程控制块(PCB)结构体来管理每一个进程资源。如图:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc3Vvb2w=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

而进程资源分为:

内核空间进程资源和用户空间进程资源

内核空间进程资源即PCB相关的信息。用户空间进程资源包含:通过成员mm_struct映射的内存空间。

进程状态

// 内核进程结构
#define TASK_RUNNING 0 // 就绪
#define TASK_INTERRUPTIBLE 1 // 中断等待
#define TASK_UNINTERRUPTIBLE 2 // 不可中断等待
#define __TASK_STOPPED 4 // 僵死
#define __TASK_TRACED 8 // 暂停
/* in tsk->exit_state */
#define EXIT_ZOMBIE 16
#define EXIT_DEAD 32
/* in tsk->state again */
#define TASK_DEAD 64
#define TASK_WAKEKILL 128
#define TASK_WAKING 256

系统中的每一个进程都必定处于以上所列进程状态中的一种。

TASK_RUNNING表示进程要么正在运行。要么正要准备运行。

TASK_INTERRUPTIBLE表示进程被堵塞(睡眠),直到某个条件变为真。条件一旦达成。进程的状态就被设置为TASK_RUNNING。

TASK_UNINTERRUPTIBLE的意义与TASK_INTERRUPTIBLE类似。除了不能通过接受一个信号来唤醒以外。

__TASK_STOPPED表示进程被停止运行。

__TASK_TRACED表示进程被debugger等进程监视。

EXIT_ZOMBIE表示进程的运行被终止,可是其父进程还没有使用wait()等系统调用来获知它的终止信息。

EXIT_DEAD表示进程的终于状态。

EXIT_ZOMBIE和EXIT_DEAD也能够存放在exit_state成员中。进程状态的切换过程和原因大致例如以下图(图片来自《Linux Kernel Development》)

进程基本属性

进程号(PID)

PID是系统维护的唯一标示一个进程的正整数。进程号是无法在用户层改动的。

在Linux系统中,系统的第一个用户进程是init进程。PID是1,其它的进程的PID依次添加。例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc3Vvb2w=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

在应用编程中能够使用getpid()函数获取当前进程的PID.详细參见:http://pubs.opengroup.org/onlinepubs/009695399/functions/getpid.html

父进程号(PPID)

除init进程外的全部进程都是由还有一进程创建的。该进程成为父进程,被创建的进程成为子进程。

PPID一样无法在用户层改动。

使用getppid()函数获取当前进程的父进程号。參见:http://pubs.opengroup.org/onlinepubs/009695399/functions/getppid.html

进程组号(PGID)

和用户管理一样,进程也有自己的进程号(PID)和进程组号(PGID)。进程组是一个或多个进程的集合。他们与同一个作业相关联。能够接受来自同一个终端的各种信号,可是进程组号能够在用户层改动。

使用getpgid()函数获取指定进程的进程组号。详见:http://pubs.opengroup.org/onlinepubs/009695399/functions/getpgid.html

以下一个程序是总和上面三个函数使用的演示样例:

#include<stdio.h>
#include<unistd.h>
int main(int argc,char *argv[])
{
int i;
printf("\tpid\t ppid \t pgid\n"); // 提示信息
printf("parent\t%d\t%d\t%d\n",getpid(),getppid(),getpgid(0)); // 当前进程信息
for(i=0;i<2;i++)
if(fork()==0)
printf("child\t%d\t%d\t%d\n",getpid(),getppid(),getpgid(0)); // 子进程信息
return 0;
}

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc3Vvb2w=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

此外,getpgrp()也能够用来获取当前进程的进程组号。

參见:http://pubs.opengroup.org/onlinepubs/009695399/functions/getpgrp.html

会话

会话(session)是一个或多个进程的合集。

系统调用函数getsid()用来获取某个进程会话的SID。

參见:http://pubs.opengroup.org/onlinepubs/009695399/functions/getsid.html

某进程的sid是能够改动的,函数setsid()用于创建新的会话。

here : http://pubs.opengroup.org/onlinepubs/009695399/functions/setsid.html

控制终端

会话和进程组有例如以下特点:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc3Vvb2w=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

为了让终端设备驱动程序将信号送到进程。能够调用tcgetpgrp()获取前台进程组的进程组号。返回与打开的终端相关联的前台进程组号。http://pubs.opengroup.org/onlinepubs/009695399/functions/tcgetpgrp.html

tcsetpgrp()函数用来设置某个进程组是前台还是后台进程组。http://pubs.opengroup.org/onlinepubs/009695399/functions/tcsetpgrp.html

假设进程有一个控制终端,则将前台进程组ID设置为pgrpid,这个值应该在用一个会话中的一个进程组的id,參数fileds是控制终端文件描写叙述符。

tcgetsid(*)函数获取当前控制终端的会话首进程的会话id。http://pubs.opengroup.org/onlinepubs/009695399/functions/tcgetsid.html

以下是使用上面的函数演示样例:

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
int main()
{
int fd;
pid_t pid;
pid=fork(); // 创建新进程
if(pid==-1)
perror("fork");
else if(pid>0)
{
wait(NULL);
exit(EXIT_FAILURE);
}
else
{
if((fd=open("/dev/pts/0",O_RDWR))==-1) // 由于是网络终端,在此打开终端以确认
{
perror("open");
}
printf("pid=%d,ppid=%d\n",getpid(),getppid()); // 获取进程号& 父进程
printf("sid=%d,tcgetsid=%d\n",getsid(getpid()),tcgetsid(fd)); // 读取会话sid和终端sid
printf("tcgetpgrp=%d\n",tcgetpgrp(fd)); // 读取终端前台进程
printf("pigd=%d\n",getpgid(getpid())); // 读取进程组的ID
}
}

执行结果:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc3Vvb2w=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

进程用户属性

Linux是权限哟有严格控制的操作系统,某个进程拥有真实的用户号(RUID)、真有用户组号(RGID)、有效用户号(EUID)、有效用户组号(EGID)信息。

在Linux系统中,文件的创建者是文件的拥有者,即文件的真有用户号为文件的拥有者号,使用ls -l 命令查看。

进程真有用户号(RUID)

对于进程而言,创建该进程的用户uid即是此进程的真有用户号。使用getuid(0函数获取当前进程的RUID。函数定义在unistd.h中。

详细參见:http://pubs.opengroup.org/onlinepubs/009695399/functions/getuid.html

进程有效用户组号(EUID)

主要用于权限检查。

多数情况下,EUID和UID同样,可是假设可执行文件的setuid位有效,则该文件的拥有者之外的用户在执行程序时,EUID和UID不一样。即当某个可执行文件设置了  setgid位后。不论什么用户(包含root)执行此程序时。其有效用户组EUID为该文件的拥有者。sunch as:

注意setuid位的特殊性,这个以后会专门解说。

进程用户组号(GID)

创建进程的用户所在的组号为该进程的用户组号(GID)。能够调用getgid()函数来获取当前进程的真有用户组号。

详细參见:http://pubs.opengroup.org/onlinepubs/009695399/functions/getgid.html

以下是读取当前进程的UID/GID/EUID/EGID的演示样例程序:

#include<stdio.h>
#include<unistd.h>
int main(int argc,char *argv[])
{
printf("\tuid\tgid\teuid\tegid\n");
printf("parent\t%d\t%d\t%d\t%d\n",getuid(),getgid(),geteuid(),getegid());
if(fork()==0)
{
printf("child\t%d\t%d\t%d\t%d\n",getuid(),getgid(),geteuid(),getegid());
}
return 0;
}

Next

进程管理及控制

Linux 特殊进程

转载请注明出处。http://blog.csdn.net/suool/article/details/38406211,谢谢!

版权声明:本文博主原创文章。博客,未经同意不得转载。

Linux 编程学习笔记----过程管理和项目发展(在)的更多相关文章

  1. Linux 编程学习笔记----动笔makefile档

    Befroe Beginning. 在设置暑假的plan ,关于Linux的书籍如今在看的是ALP和Linux高级程序设计(杨宗德)第三版.在计划中的是Linux高级环境编程. 如今開始关于Linux ...

  2. Linux 编程学习笔记----文档管理系统

    本文从网络上完成的第 Linux在文件系统管理. 1.VFS文件系统概述 linux採用VFS来管理文件系统,并且linux设计的原则之中的一个就是everything is file.因此文件管理系 ...

  3. Linux 编程学习笔记----ANSI C 文件I/O管理

    转载请注明出处:http://blog.csdn.net/suool/article/details/38129201 问题引入 文件的种类 依据数据存储的方式不同,能够将文件分为文本文件和二进制文件 ...

  4. Linux 编程学习笔记----命令行参数处理

    转载请注明出处.http://blog.csdn.net/suool/article/details/38089001 问题引入----命令行參数及解析 在使用linux时,与windows最大的不同 ...

  5. Linux编程学习笔记(二)

    续上个章节,这个章节主要是Linux的远程登录系统操作笔记 一. Linux一般作为服务器使用,但是服务器都是在机房的,所以不可能经常跑到机房去操作系统,所以使用远程登录系统,在Linux的系统一般使 ...

  6. Linux编程学习笔记(一)

    Linux的发展趋势势在必行,国内的服务器的操作系统Linux占到主导地位,不光是操作系统,还有嵌入式系统. 1. 今天就Linux的其中一个版本做一介绍,如下是Centos的版本之间的区别. ins ...

  7. LINUX编程学习笔记(十四) 创建进程与 父子进程内存空间

    1什么是进程:进程是一个执行中的程序 执行的程序: 代码->资源->CPU 进程有很多数据维护:进程状态/进程属性 所有进程属性采用的一个树形结构体维护 ps  -a//所有进程 ps - ...

  8. Linux编程学习笔记 -- Process

    进程是一个程序的运行.   在一个程序中执行另一个执程序的方法有两种: 1)system 在shell中执行程序 2)fork + exec 复制一个进程,在进程中用新的程序替换原有的程序   for ...

  9. LINUX编程学习笔记(十三) 遍历目录的两种方法

    1 默认情况下  实际用户和有效用户是一样的 实际用户:执行用户   有效用户:权限用户 getuid()  实际用户 geteuid() 有效用户 chmod u+s 之后 ,其他人执行文件时,实际 ...

随机推荐

  1. Java 模拟队列(一般队列、双端队列、优先级队列)

    队列: 先进先出,处理类似排队的问题,先排的.先处理,后排的等前面的处理完了,再处理 对于插入和移除操作的时间复杂度都为O(1).从后面插入,从前面移除 双端队列: 即在队列两端都能够insert和r ...

  2. [置顶] android系统功能调用大全

    1.从google搜索内容  Intent intent = new Intent();  intent.setAction(Intent.ACTION_WEB_SEARCH);  intent.pu ...

  3. UVA 11768 - Lattice Point or Not(数论)

    UVA 11768 - Lattice Point or Not option=com_onlinejudge&Itemid=8&page=show_problem&categ ...

  4. poj 1198 hdu 1401 搜索+剪枝 Solitaire

    写到一半才发现能够用双向搜索4层来写,但已经不愿意改了,干脆暴搜+剪枝水过去算了. 想到一个非常水的剪枝,h函数为  当前点到终点4个点的最短距离加起来除以2.由于最多一步走2格,然后在HDU上T了, ...

  5. xcode多target

    原文:http://www.codza.com/free-iphone-app-version-from-the-same-xcode-project There are more than 15,0 ...

  6. extjs_11_mvc模式

    1.非mvc模式 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWRhbV93enM=/font/5a6L5L2T/fontsize/400/fill/I ...

  7. 用Javascript评估用户输入密码的强度(Knockout版)

    原文:用Javascript评估用户输入密码的强度(Knockout版) 早上看到博友6点多发的一篇关于密码强度的文章(连接),甚是感动(周末大早上还来发文). 我们来看看如果使用Knockout更简 ...

  8. Mysql 双向关联触发器

    双向关联触发器 //增加 delimiter // create trigger InsertDemo AFTER insert on vaccine.demo for each row Begin ...

  9. 如何添加地图控件到Windows Phone 8的页面中

    原文 如何添加地图控件到Windows Phone 8的页面中 本主题介绍了各种方法来添加一个地图控件到Windows Phone 8的项目.该地图控件在Windows Phone的SDK 8.0的库 ...

  10. ubuntu 12.10 软件更新源列表

    ubuntu 12.10正式版已经发布了,国内各大开源软件源也陆续更新了资源.今天分享一下ubuntu 12.10 软件更新源列表. 首先,习惯性的备份一下ubuntu 12.04 原来的源地址列表文 ...