在unix/linux下,经常有因为共享内存、信号量,队列等共享信息没有干净地清楚而引起一些问题。
查看共享信息的内存的命令是ipcs [-m|-s|-q]。
默认会列出共享内存、信号量,队列信息,-m列出共享内存,-s列出共享信号量,-q列出共享队列。
怎样清楚呢?
清楚命令是ipcrm [-m|-s|-q] id。
-m 删除共享内存,-s删除共享信号量,-q删除共享队列。
下面是一个操作示例:
view plaincopy to clipboardprint?
[ora@localhost ora]$ ipcs
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x0399ef4c 262145 ora 660 255852544 55 &nb ......
为内核寻找新进程在cpu上运行时,必须只考虑可运行进程(TASK_RUNNING)。
提高调度程序运行速度的诀窍是建立多个可运行进程链表,每种进程优先权对应一个不同的链表。每个task_struct描述符包含一个list_head类型的字段run_list。如果进程的优先权等于k(0-139),run_list字段把该进程链入优先权为k的可运行进程的链表中。
内核必须为系统中每个运行队列保存大量的数据,不过运行队列的主要结构还是组成运行队列的进程描述符表,所有这些链表都由一个单独的prio_array_t数据结构来实现。
185 struct prio_array {
186 unsigned int nr_active; 链表中进程描述符的数量
187 unsigned long bitmap[BITMAP_SIZE]; 优先权位图:当且仅当某个优先权的进程链表不为空时设置相应的位标志
188 struct list_head queue[MAX_PRIO]; 140个优先权队列的头结点
189 };
static void enqueue_task(struct task_struct *p, prio_arra ......
散列(hash)函数并不总能确保pid与表索引一一对应。两个不同的pid散列到相同的表索引称为冲突(colliding),linux利用链表来处理冲突的pid,每一个表项是由冲突的进程描述符组成的双向链表。
pid散列表的数据结构解决了所有这些难题,他们可以为包含在一个散列表中的任何pid号定义进程链表。最主要的数据结构是四个pid结构的数组,它在进程描述符的pid字段中。
struct pid
{
/* Try to keep pid_chain in the same cacheline as nr for find_pid */
int nr;pid的数值
struct hlist_node pid_chain;/* list of pids with the same nr, only one of them is in the hash */链接散列链表的下一个和前一个元素
struct list_head pid_list;每个pid的进程链表头
};
基本运作:pid_hash中的四个基本类型表头找到tgid哈希表,然后找到对应表项再进一步找到进程描述符中的pid_chain字段,然后进一步找到process descriptor中的pid_chain表项,然后找到哈希表。
处理pid散列表的函数和宏: ......
等待队列在内核中很多用途,尤其用在中断处理、进程同步及定时。等待队列实现了在事件上的条件等待:希望等待特定事件的进程把自己放进合适的等待队列,并放弃控制权。因此,等待队列表示一组睡眠的进程,当某一条件变为真时,由内核唤醒它们。
等待队列由双向链表实现,其元素包括指向进程描述符的指针。每个队列都有一个等待队列头,等待队列头是一个类型为wait_queue_head_t的数据结构。
struct __wait_queue_head {
spinlock_t lock;
struct list_head task_list;
};
typedef struct __wait_queue_head wait_queue_head_t;
等待队列由中断处理程序和主要内核函数修改。同步是通过等待队列头中的lock自旋锁达到的,task_list字段是等待进程链表的头。
等待队列链表中的元素类型为wait_queue_t:
struct __wait_queue {
unsigned int flags;
#define WQ_FLAG_EXCLUSIVE 0x01
struct task_struct * task;
& ......
每个进程都有一组相关的资源限制(resource limit),限制了指定进程能使用的系统资源数量。
对当前进程的资源限制存放在current->signal->rlim字段,进程的信号描述符的一个字段。该字段类型为rlimit结构的数组,每个资源限制对应一个元素。
struct rlimit {
unsigned long rlim_cur;
unsigned long rlim_max;
};
其中rlim_cur字段是资源的当前资源限制(current->signal->rlim[RLIMIT_CPU])。rlim_cur表示正运行进程所占用cpu时间的当前限制
rlim_max字段是资源限制所允许的最大值。利用getrlimit()和setrlimit()系统调用,用户总能把一些资源的rlim_cur限制增加到rlim_max。只有超级用户(具有CAP_SYS_RESOURCE权能的用户)才能改变rlim_max字段,或把rlim_cur字段设置成大于相应rlim_max字段的一个值。
大多数资源限制包含数值RLIM_INFINITY(0xffffffff),它意味着没有对相应的资源施加用户限制。
#ifndef __ARCH_RLIMIT_ORDER
#define RLIMIT_CPU   ......
/* 他通过只复制内存页面来复制一定范围内的线性地址的内容*/
00150int copy_page_tables(unsigned long from,unsigned long to,long size)
00151 {
00152 unsigned long * from_page_table;
00153 unsigned long * to_page_table;
00154 unsigned long this_page;
00155 unsigned long * from_dir, * to_dir;
00156 unsigned long nr;
00157 //下面是判断from 和to 是否在4M的边界处
00158 if ((from&0x3fffff) || (to&0x3fffff))
00159 panic("copy_page_tables called with wrong alignment");
//赋給from_dir 页目录表的源目录起始号 (from>>20)&oxfffc =(from>>22)<<2
00160 from_dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */
//赋給to_d ......