linux编程内容,LINUX编程学习2,补充内容

task_struct结构注释

==========================

long state 任务的运行状态(-1 不可运行,0 可运行(就绪),>0

已停止)。

long counter 任务运行时间计数(递减)(滴答数),运行时间片。

long priority 运行优先数。任务开始运行时counter = priority,越大运行越长。

long signal 信号。是位图,每个比特位代表一种信号,信号值=位偏移值+1。

struct sigaction sigaction[32] 信号执行属性结构,对应信号将要执行的操作和标志信息。

long blocked 进程信号屏蔽码(对应信号位图)。

--------------------------

int exit_code 任务执行停止的退出码,其父进程会取。

unsigned long start_code 代码段地址。

unsigned long end_code 代码长度(字节数)。

unsigned long end_data 代码长度 + 数据长度(字节数)。

unsigned long brk 总长度(字节数)。

unsigned long start_stack 堆栈段地址。

long pid 进程标识号(进程号)。

long father 父进程号。

long pgrp 父进程组号。

long session 会话号。

long leader 会话首领。

unsigned short uid 用户标识号(用户id)。

unsigned short euid 有效用户id。

unsigned short suid 保存的用户id。

unsigned short gid 组标识号(组id)。

unsigned short egid 有效组id。

unsigned short sgid 保存的组id。

long alarm 报警定时值(滴答数)。

long utime 用户态运行时间(滴答数)。

long stime 系统态运行时间(滴答数)。

long cutime 子进程用户态运行时间。

long cstime 子进程系统态运行时间。

long start_time 进程开始运行时刻。

unsigned short used_math 标志:是否使用了协处理器。

--------------------------

int tty 进程使用tty 的子设备号。-1 表示没有使用。

unsigned short umask 文件创建属性屏蔽位。

struct m_inode * pwd 当前工作目录i 节点结构。

struct m_inode * root 根目录i 节点结构。

struct m_inode * executable 执行文件i 节点结构。

unsigned long close_on_exec

执行时关闭文件句柄位图标志。(参见include/fcntl.h)

struct file * filp[NR_OPEN] 进程使用的文件表结构。

--------------------------

struct desc_struct ldt[3]

本任务的局部表描述符。0-空,1-代码段cs,2-数据和堆栈段ds&ss。

--------------------------

struct tss_struct tss 本进程的任务状态段信息结构。

1. 调度数据成员

(1) volatile long states;

表示进程的当前状态:

* TASK_RUNNING:正在运行或在就绪队列run-queue中准备运行的进程,实际参与进程调度。

*

TASK_INTERRUPTIBLE:处于等待队列中的进程,待资源有效时唤醒,也可由其它进程通过信号(signal)或定时中断唤醒后进入就绪队列

run-queue。

*

TASK_UNINTERRUPTIBLE:处于等待队列中的进程,待资源有效时唤醒,不可由其它进程通过信号(signal)或定时中断唤醒。

*

TASK_ZOMBIE:表示进程结束但尚未消亡的一种状态(僵死状态)。此时,进程已经结束运行且释放大部分资源,但尚未释放进程控制块。

*TASK_STOPPED:进程被暂停,通过其它进程的信号才能唤醒。导致这种状态的原因有二,或者是对收到SIGSTOP、SIGSTP、

SIGTTIN或SIGTTOU信号的反应,或者是受其它进程的ptrace系统调用的控制而暂时将CPU交给控制进程。

* TASK_SWAPPING: 进程页面被交换出内存的进程。

(2) unsigned long flags;

进程标志:

*PF_ALIGNWARN 打印“对齐”警告信息。

*PF_PTRACED 被ptrace系统调用监控。

*PF_TRACESYS 正在跟踪。

*PF_FORKNOEXEC 进程刚创建,但还没执行。

*PF_SUPERPRIV 超级用户特权。

*PF_DUMPCORE dumped core。

*PF_SIGNALED 进程被信号(signal)杀出。

*PF_STARTING 进程正被创建。

*PF_EXITING 进程开始关闭。

*PF_USEDFPU 该进程使用FPU(SMP only)。

*PF_DTRACE delayed trace (used on m68k)。

(3) long priority;

进程优先级。

Priority的值给出进程每次获取CPU后可使用的时间(按jiffies计)。优先级可通过系统调用sys_setpriorty改变(在

kernel/sys.c中)。

(4) unsigned long rt_priority;

rt_priority

给出实时进程的优先级,rt_priority+1000给出进程每次获取CPU后可使用的时间(同样按jiffies计)。实时进程的优先级可通过系统

调用sys_sched_setscheduler()改变(见kernel/sched.c)。

(5) long counter;

轮转法调度时表示进程当前还可运行多久。在进程开始运行是被赋为priority的值,以后每隔一个tick(时钟中断)递减1,减到0时引起新一轮调

度。重新调度将从run_queue队列选出counter值最大的就绪进程并给予CPU使用权,因此counter起到了进程的动态优先级的作用

(priority则是静态优先级)。

(6) unsigned long policy;

该进程的进程调度策略,可以通过系统调用sys_sched_setscheduler()更改(见kernel/sched.c)。调度策略有:

*SCHED_OTHER 0 非实时进程,基于优先权的轮转法(round robin)。

*SCHED_FIFO 1 实时进程,用先进先出算法。

*SCHED_RR 2 实时进程,用基于优先权的轮转法。

2. 信号处理

(1) unsigned long signal;

进程接收到的信号。每位表示一种信号,共32种。置位有效。

(2) unsigned long blocked;

进程所能接受信号的位掩码。置位表示屏蔽,复位表示不屏蔽。

(3) struct signal_struct *sig;

为signal和blocked都是32位的变量,Linux最多只能接受32种信号。对每种信号,各进程可以由PCB的sig属性选择使用自定义的处理

函数,或是系统的缺省处理函数。指派各种信息处理函数的结构定义在include/linux/sched.h中。对信号的检查安排在系统调用结束后,以

及“慢速型”中断服务程序结束后(IRQ#_interrupt(),参见9。5节“启动内核”)。

3. 进程队列指针

(1) struct task_struct *next_task,*prev_task;

所有进程(以PCB的形式)组成一个双向链表。next_task和就是链表的前后指针。链表的头和尾都是init_task(即0号进程)。

(2) struct task_struct *next_run,*prev_run;

由正在运行或是可以运行的,其进程状态均为TASK_RUNNING的进程所组成的一个双向循环链表,即run_queue就绪队列。该链表的前后向指针用next_run和prev_run,链表的头和尾都是init_task(即0号进程)。

(3) struct task_struct *p_opptr,*p_pptr;和struct task_struct

*p_cptr,*p_ysptr,*p_osptr;

以上分别是指向原始父进程(original parent)、父进程(parent)、子进程(youngest

child)及新老兄弟进程(younger sibling,older sibling)的指针。

4. 进程标识

(1) unsigned short uid,gid;

uid和gid是运行进程的用户标识和用户组标识。

(2) int groups[NGROUPS];

与多数现代UNIX操作系统一样,Linux允许进程同时拥有一组用户组号。在进程访问文件时,这些组号可用于合法性检查。

(3) unsigned short euid,egid;

euid

和egid又称为有效的uid和gid。出于系统安全的权限的考虑,运行程序时要检查euid和egid的合法性。通常,uid等于euid,gid等于

egid。有时候,系统会赋予一般用户暂时拥有root的uid和gid(作为用户进程的euid和egid),以便于进行运作。

(4) unsigned short fsuid,fsgid;

fsuid

和fsgid称为文件系统的uid和gid,用于文件系统操作时的合法性检查,是Linux独特的标识类型。它们一般分别和euid和egid一致,但在

NFS文件系统中NFS服务器需要作为一个特殊的进程访问文件,这时只修改客户进程的fsuid和fsgid。

(5) unsigned short suid,sgid;

suid和sgid是根据POSIX标准引入的,在系统调用改变uid和gid时,用于保留真正的uid和gid。

(6) int pid,pgrp,session;

进程标识号、进程的组织号及session标识号,相关系统调用(见程序kernel/sys.c)有sys_setpgid、sys_getpgid、

sys_setpgrp、sys_getpgrp、sys_getsid及sys_setsid几种。

(7) int leader;

是否是session的主管,布尔量。

5. 时间数据成员

(1) unsigned long timeout;

用于软件定时,指出进程间隔多久被重新唤醒。采用tick为单位。

(2) unsigned long it_real_value,it_real_iner;

用 于itimer(interval

timer)软件定时。采用jiffies为单位,每个tick使it_real_value减到0时向进程发信号SIGALRM,并重新置初值。初值由

it_real_incr保存。具体代码见kernel/itimer.c中的函数it_real_fn()。

(3) struct timer_list real_timer;

一种定时器结构(Linux共有两种定时器结构,另一种称作old_timer)。数据结构的定义在include/linux/timer.h中,相关操作函数见kernel/sched.c中add_timer()和del_timer()等。

(4) unsigned long it_virt_value,it_virt_incr;

于进程用户态执行时间的itimer软件定时。采用jiffies为单位。进程在用户态运行时,每个tick使it_virt_value减1,减到0时

向进程发信号SIGVTALRM,并重新置初值。初值由it_virt_incr保存。具体代码见kernel/sched.c中的函数

do_it_virt()。

(5) unsigned long it_prof_value,it_prof_incr;

同样是

itimer软件定时。采用jiffies为单位。不管进程在用户态或内核态运行,每个tick使it_prof_value减1,减到0时向进程发信号

SIGPROF,并重新置初值。初值由it_prof_incr保存。

具体代码见kernel/sched.c中的函数do_it_prof。

(6) long utime,stime,cutime,cstime,start_time;

以上分别为进程在用户态的运行时间、进程在内核态的运行时间、所有层次子进程在用户态的运行时间总和、所有层次子进程在核心态的运行时间总和,以及创建该进程的时间。

6. 信号量数据成员

(1) struct sem_undo *semundo;

程每操作一次信号量,都生成一个对此次操作的undo操作,它由sem_undo结构描述。这些属于同一进程的undo操作组成的链表就由semundo

属性指示。当进程异常终止时,系统会调用undo操作。sem_undo的成员semadj指向一个数据数组,表示各次undo的量。结构定义在

include/linux/sem.h。

(2) struct sem_queue *semsleeping;

每一信号量集合对应一

个sem_queue等待队列(见include/linux/sem.h)。进程因操作该信号量集合而阻塞时,它被挂到semsleeping指示的关

于该信号量集合的sem_queue队列。反过来,semsleeping。sleeper指向该进程的PCB。

7. 进程上下文环境

(1) struct desc_struct *ldt;

进程关于CPU段式存储管理的局部描述符表的指针,用于仿真WINE

Windows的程序。其他情况下取值NULL,进程的ldt就是arch/i386/traps.c定义的default_ldt。

(2) struct thread_struct tss;

任务状态段,其内容与INTEL

CPU的TSS对应,如各种通用寄存器.CPU调度时,当前运行进程的TSS保存到PCB的tss,新选中进程的tss内容复制到CPU的TSS。结构定义在include/linux/tasks.h中。

(3) unsigned long saved_kernel_stack;

为MS-DOS的仿真程序(或叫系统调用vm86)保存的堆栈指针。

(4) unsigned long kernel_stack_page;

在内核态运行时,每个进程都有一个内核堆栈,其基地址就保存在kernel_stack_page中。

8. 文件系统数据成员

(1) struct fs_struct *fs;

fs

保存了进程本身与VFS的关系消息,其中root指向根目录结点,pwd指向当前目录结点,umask给出新建文件的访问模式(可由系统调用umask更

改),count是Linux保留的属性,如下页图所示。结构定义在include/linux/sched.h中。

(2) struct files_struct *files;

files包含了进程当前所打开的文件(struct file

*fd[NR_OPEN])。在Linux中,一个进程最多只能同时打开NR_OPEN个文件。而且,前三项分别预先设置为标准输入、标准输出和出错消息输出文件。

(3) int link_count;

文件链(link)的数目。

9. 内存数据成员

(1) struct mm_struct *mm;

在linux

中,采用按需分页的策略解决进程的内存需求。task_struct的数据成员mm指向关于存储管理的mm_struct结构。其中包含了一个虚存队列

mmap,指向由若干vm_area_struct描述的虚存块。同时,为了加快访问速度,mm中的mmap_avl维护了一个AVL树。在树中,所有的

vm_area_struct虚存块均由左指针指向相邻的低虚存块,右指针指向相邻的高虚存块。

结构定义在include/linux/sched.h中。

10. 页面管理

(1) int swappable:1;

进程占用的内存页面是否可换出。swappable为1表示可换出。对该标志的复位和置位均在do_fork()函数中执行(见

kerenl/fork.c)。

(2) unsigned long swap_address;

虚存地址比swap_address低的进程页面,以前已经换出或已换出过,进程下一次可换出的页面自swap_address开始。参见

swap_out_process()和swap_out_pmd()(见mm/vmscan.c)。

(3) unsigned long min_flt,maj_flt;

进程累计的minor缺页次数和major缺页次数。maj_flt基本与min_flt相同,但计数的范围比后者广(参见fs/buffer.c和

mm/page_alloc.c)。min_flt只在do_no_page()、do_wp_page()里(见mm/memory.c)计数新增的可

以写操作的页面。

(4) unsigned long nswap;

该进程累计换出的页面数。

(5) unsigned long cmin_flt,cmaj_flt,cnswap;

以本进程作为祖先的所有层次子进程的累计换入页面、换出页面计数。

(6) unsigned long old_maj_flt,dec_flt;

(7) unsigned long swap_cnt;

下一次信号最多可换出的页数。

11. 支持对称多处理器方式(SMP)时的数据成员

(1) int processor;

进程正在使用的CPU。

(2) int last_processor;

进程最后一次使用的CPU。

(3) int lock_depth;

上下文切换时系统内核锁的深度。

12. 其它数据成员

(1) unsigned short used_math;

是否使用FPU。

(2) char comm[16];

进程正在运行的可执行文件的文件名。

(3) struct rlimit rlim[RLIM_NLIMITS];

构rlimit用于资源管理,定义在linux/include/linux/resource.h中,成员共有两项:rlim_cur是资源的当前最大

数目;rlim_max是资源可有的最大数目。在i386环境中,受控资源共有RLIM_NLIMITS项,即10项,定义在

linux/include/asm/resource.h中,见下表:

(4) int errno;

最后一次出错的系统调用的错误号,0表示无错误。系统调用返回时,全程量也拥有该错误号。

(5) long debugreg[8];

保存INTEL CPU调试寄存器的值,在ptrace系统调用中使用。

(6) struct exec_domain *exec_domain;

Linux可以运行由80386平台其它UNIX操作系统生成的符合iBCS2标准的程序。关于此类程序与Linux程序差异的消息就由

exec_domain结构保存。

(7) unsigned long personality;

Linux 可以运行由80386平台其它UNIX操作系统生成的符合iBCS2标准的程序。

Personality进一步描述进程执行的程序属于何种UNIX平台的“个性”信息。通常有PER_Linux、PER_Linux_32BIT、

PER_Linux_EM86、PER_SVR3、PER_SCOSVR3、PER_WYSEV386、PER_ISCR4、PER_BSD、

PER_XENIX和PER_MASK等,参见include/linux/personality.h。

(8) struct linux_binfmt *binfmt;

指向进程所属的全局执行文件格式结构,共有a。out、script、elf和java等四种。结构定义在include/linux

/binfmts.h中(core_dump、load_shlib(fd)、load_binary、use_count)。

(9) int exit_code,exit_signal;

引起进程退出的返回代码exit_code,引起错误的信号名exit_signal。

(10) int dumpable:1;

布尔量,表示出错时是否可以进行memory dump。

(11) int did_exec:1;

按POSIX要求设计的布尔量,区分进程是正在执行老程序代码,还是在执行execve装入的新代码。

(12) int tty_old_pgrp;

进程显示终端所在的组标识。

(13) struct tty_struct *tty;

指向进程所在的显示终端的信息。如果进程不需要显示终端,如0号进程,则该指针为空。结构定义在include/linux/tty.h中。

(14) struct wait_queue *wait_chldexit;

在进程结束时,或发出系统调用wait4后,为了等待子进程的结束,而将自己(父进程)睡眠在该队列上。结构定义在include/linux

/wait.h中。

13. 进程队列的全局变量

(1) current;

当前正在运行的进程的指针,在SMP中则指向CPU组中正被调度的CPU的当前进程:

#define current(0+current_set[smp_processor_id()])

struct task_struct *current_set[NR_CPUS];

(2) struct task_struct init_task;

即0号进程的PCB,是进程的“根”,始终保持初值INIT_TASK。

(3) struct task_struct *task[NR_TASKS];

程队列数组,规定系统可同时运行的最大进程数(见kernel/sched.c)。NR_TASKS定义在include/linux/tasks.h

中,值为512。每个进程占一个数组元素(元素的下标不一定就是进程的pid),task[0]必须指向init_task(0号进程)。可以通过

task[]数组遍历所有进程的PCB。但Linux也提供一个宏定义for_each_task()(见

include/linux/sched.h),它通过next_task遍历所有进程的PCB:

#define for_each_task(p) \

for(p=&init_task;(p=p->next_task)!=&init_task;)

(4) unsigned long volatile jiffies;

Linux的基准时间(见kernal/sched.c)。系统初始化时清0,以后每隔10ms由时钟中断服务程序do_timer()增1。

(5) int need_resched;

重新调度标志位(见kernal/sched.c)。当需要Linux调度时置位。在系统调用返回前(或者其它情形下),判断该标志是否置位。置位的话,马上调用schedule进行CPU调度。

(6) unsigned long intr_count;

录中断服务程序的嵌套层数(见kernal/softirq.c)。正常运行时,intr_count为0。当处理硬件中断、执行任务队列中的任务或者执

行bottom half队列中的任务时,intr_count非0。这时,内核禁止某些操作,例如不允许重新调度。

在linux 中每一个进程都由task_struct 数据结构来定义.

task_struct就是我们通常所说的PCB.她是对进程控制的唯一手段也是最有效的手段. 当我们调用fork() 时,

系统会为我们产生一个task_struct结构。然后从父进程,那里继承一些数据, 并把新的进程插入到进程树中,

以待进行进程管理。因此了解task_struct的结构对于我们理解任务调度(在linux 中任务和进程是同一概念)的关键。

在进行剖析task_struct的定义之前,我们先按照我们的理论推一下它的结构:

1、进程状态 ,将纪录进程在等待,运行,或死锁

2、调度信息, 由哪个调度函数调度,怎样调度等

3、进程的通讯状况

4、因为要插入进程树,必须有联系父子兄弟的指针, 当然是task_struct型

5、时间信息, 比如计算好执行的时间, 以便cpu 分配

6、标号 ,决定改进程归属

7、可以读写打开的一些文件信息

8、 进程上下文和内核上下文

9、处理器上下文

10、内存信息

因为每一个PCB都是这样的, 只有这些结构,

才能满足一个进程的所有要求。打开/include/linux/sched.h可以找到task_struct 的定义

struct task_struct {

volatile long state; //说明了该进程是否可以执行,还是可中断等信息

unsigned long flags; //Flage

是进程号,在调用fork()时给出

int

sigpending; //进程上是否有待处理的信号

mm_segment_t addr_limit; //进程地址空间,区分内核进程与普通进程在内存存放的位置不同

//0-0xBFFFFFFF for user-thead

//0-0xFFFFFFFF for kernel-thread

//调度标志,表示该进程是否需要重新调度,若非0,则当从内核态返回到用户态,会发生调度

volatile long need_resched;

int lock_depth; //锁深度

long

nice; //进程的基本时间片

//进程的调度策略,有三种,实时进程:SCHED_FIFO,SCHED_RR, 分时进程:SCHED_OTHER

unsigned long policy;

struct mm_struct *mm; //进程内存管理信息

int processor;

//若进程不在任何CPU上运行, cpus_runnable 的值是0,否则是1 这个值在运行队列被锁时更新

unsigned long cpus_runnable, cpus_allowed;

struct list_head run_list; //指向运行队列的指针

unsigned long sleep_time; //进程的睡眠时间

//用于将系统中所有的进程连成一个双向循环链表, 其根是init_task

struct task_struct *next_task, *prev_task;

struct mm_struct *active_mm;

struct list_head

local_pages; //指向本地页面 unsigned int allocation_order, nr_local_pages;

struct linux_binfmt *binfmt; //进程所运行的可执行文件的格式

int exit_code, exit_signal;

int

pdeath_signal; //父进程终止是向子进程发送的信号

unsigned long personality;

//Linux可以运行由其他UNIX操作系统生成的符合iBCS2标准的程序

int did_exec:1;

pid_t pid; //进程标识符,用来代表一个进程

pid_t pgrp; //进程组标识,表示进程所属的进程组

pid_t tty_old_pgrp; //进程控制终端所在的组标识

pid_t session; //进程的会话标识

pid_t tgid;

int

leader; //表示进程是否为会话主管

struct task_struct

*p_opptr,*p_pptr,*p_cptr,*p_ysptr,*p_osptr;

struct list_head thread_group; //线程链表

struct task_struct *pidhash_next; //用于将进程链入HASH表

struct task_struct **pidhash_pprev;

wait_queue_head_t wait_chldexit; //供wait4()使用

struct completion *vfork_done; //供vfork()

使用

unsigned long rt_priority; //实时优先级,用它计算实时进程调度时的weight值

//it_real_value,it_real_incr用于REAL定时器,单位为jiffies,

系统根据it_real_value

//设置定时器的第一个终止时间. 在定时器到期时,向进程发送SIGALRM信号,同时根据

//it_real_incr重置终止时间,it_prof_value,it_prof_incr用于Profile定时器,单位为jiffies。

//当进程运行时,不管在何种状态下,每个tick都使it_prof_value值减一,当减到0时,向进程发送

//信号SIGPROF,并根据it_prof_incr重置时间.

//it_virt_value,it_virt_value用于Virtual定时器,单位为jiffies。当进程运行时,不管在何种

//状态下,每个tick都使it_virt_value值减一当减到0时,向进程发送信号SIGVTALRM,根据

//it_virt_incr重置初值。

unsigned long it_real_value, it_prof_value, it_virt_value;

unsigned long it_real_incr, it_prof_incr, it_virt_value;

struct timer_list real_timer; //指向实时定时器的指针

struct tms

times; //记录进程消耗的时间

unsigned long start_time; //进程创建的时间

//记录进程在每个CPU上所消耗的用户态时间和核心态时间

long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];

//内存缺页和交换信息:

//min_flt, maj_flt累计进程的次缺页数(Copy

on Write页和匿名页)和主缺页数(从映射文件或交换

//设备读入的页面数); nswap记录进程累计换出的页面数,即写到交换设备上的页面数。

//cmin_flt, cmaj_flt, cnswap记录本进程为祖先的所有子孙进程的累计次缺页数,主缺页数和换出页面数。

//在父进程回收终止的子进程时,父进程会将子进程的这些信息累计到自己结构的这些域中

unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt,

cnswap;

int swappable:1; //表示进程的虚拟地址空间是否允许换出

//进程认证信息

//uid,gid为运行该进程的用户的用户标识符和组标识符,通常是进程创建者的uid,gid

//euid,egid为有效uid,gid

//fsuid,fsgid为文件系统uid,gid,这两个ID号通常与有效uid,gid相等,在检查对于文件

//系统的访问权限时使用他们。

//suid,sgid为备份uid,gid

uid_t uid,euid,suid,fsuid;

gid_t gid,egid,sgid,fsgid;

int ngroups; //记录进程在多少个用户组中

gid_t groups[NGROUPS]; //记录进程所在的组

//进程的权能,分别是有效位集合,继承位集合,允许位集合

kernel_cap_t cap_effective, cap_inheritable, cap_permitted;

int keep_capabilities:1;

struct user_struct *user;

struct rlimit rlim[RLIM_NLIMITS]; //与进程相关的资源限制信息

unsigned short used_math; //是否使用FPU

char comm[16]; //进程正在运行的可执行文件名

//文件系统信息

int link_count, total_link_count;

//NULL if no tty 进程所在的控制终端,如果不需要控制终端,则该指针为空

struct tty_struct *tty;

unsigned int locks;

//进程间通信信息

struct sem_undo *semundo; //进程在信号灯上的所有undo操作

struct sem_queue *semsleeping; //当进程因为信号灯操作而挂起时,他在该队列中记录等待的操作

//进程的CPU状态,切换时,要保存到停止进程的task_struct中

struct thread_struct thread;

//文件系统信息

struct fs_struct *fs;

//打开文件信息

struct files_struct *files;

//信号处理函数

spinlock_t sigmask_lock;

struct signal_struct *sig; //信号处理函数

sigset_t blocked; //进程当前要阻塞的信号,每个信号对应一位

struct sigpending pending; //进程上是否有待处理的信号

unsigned long sas_ss_sp;

size_t sas_ss_size;

int (*notifier)(void *priv);

void *notifier_data;

sigset_t *notifier_mask;

u32 parent_exec_id;

u32 self_exec_id;

spinlock_t alloc_lock;

void *journal_info;

};

内存共享 shmget()函数

最近看流程调度的算法的时候,发现自己对共享内存的知识还是很单薄,加上进程间的通信就更难上加难了,

所以在网上找了些资料,对照程序理解了下,还是有不少的收获的,所以就把资料贴出来,收藏下,给自己

以后参考参考:

要使用共享内存,应该有如下步骤:

1.开辟一块共享内存 shmget()

2.允许本进程使用共某块共享内存 shmat()

3.写入/读出

4.禁止本进程使用这块共享内存 shmdt()

5.删除这块共享内存 shmctl()或者命令行下ipcrm

首先,操作共享内存,我们用到了下面的函数

#include

#include

#include

int shmget( key_t shmkey , int shmsiz , int flag );

void *shmat(

int shmid , char *shmaddr , int shmflag );

int shmdt( char *shmaddr );

shmget()是用来开辟/指向一块共享内存的函数。参数定义如下:

key_t shmkey 是这块共享内存的标识符。如果是父子关系的进程间通信的话,这个标识符用IPC_PRIVATE来代替

int shmsiz 是这块内存的大小.

int flag 是这块内存的模式(mode)以及权限标识

模式可取如下值: 新建:IPC_CREAT

使用已开辟的内存:IPC_ALLOC

如果标识符以存在,则返回错误值:IPC_EXCL

然后将“模式” 和“权限标识”进行“或”运算,做为第三个参数

如: IPC_CREAT| IPC_EXCL | 0666

这个函数成功时返回共享内存的ID,失败时返回-1。

shmat()是用来允许本进程访问一块共享内存的函数。

int shmid是那块共享内存的ID。

char *shmaddr是共享内存的起始地址

int shmflag是本进程对该内存的操作模式。如果是SHM_RDONLY的话,就是只读模式。其它的是读写模式

成功时,这个函数返回共享内存的起始地址。失败时返回-1。

shmdt()与shmat()相反,是用来禁止本进程访问一块共享内存的函数

参数char *shmaddr是那块共享内存的起始地址

成功时返回0。失败时返回-1。

此外,还有一个用来控制共享内存的shmctl()函数如下:

#include

#include

#include

int shmctl( int shmid , int cmd , struct shmid_ds *buf );

int shmid是共享内存的ID。

int cmd是控制命令,可取值如下:

IPC_STAT 得到共享内存的状态

IPC_SET 改变共享内存的状态

IPC_RMID 删除共享内存

struct shmid_ds

*buf是一个结构体指针。IPC_STAT的时候,取得的状态放在这个结构体中。如果要改变共享内存的状态,用这个结构体指定

返回值:成功:0

失败:-1

在使用共享内存,结束程序退出后。如果你没在程序中用shmctl()删除共享内存的话,一定要在命令行下用ipcrm命令删除这块共享内存。你要是不管的话,它就一直在那儿放着了。

简单解释一下ipcs命令和ipcrm命令。

取得ipc信息:

ipcs [-m|-q|-s]

-m 输出有关共享内存(shared memory)的信息

-q 输出有关信息队列(message queue)的信息

-s 输出有关“遮断器”(semaphore)的信息

%ipcs -m

删除ipc

ipcrm -m|-q|-s shm_id

%ipcrm -m 105

abort函数

函数名: abort

功 能: 异常终止一个进程

描述:abort()函数首先解除进程对SIGABRT信号的阻止,然后向调用进程发送该信号。

abort()函数会导致进程的异常终止除非SIGABRT信号被捕捉并且信号处理句柄没有返回。

abort()函数导致所有的流被关闭和冲洗。

abort()函数没有返回值:void abort(void);

用 法: void abort(void);

程序例:

#include

#include

int main(void)

{ printf("Calling abort()\n");

abort();

return 0;

}

atoi函数原型:

int atoi(char *str)

函数用途:

将字符串转换成一个整数值

输入参数:

str 待转换为整型数的字符串

返回值:

成功返回转换后的数值,失败则返回0.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值