浅谈linux的进程的静态特性——pid,进程状态,进程链表,等待队列

导数与微分在 FPS 射击游戏中的实际应用:把“手感”算出来 摘要:射击游戏开发中,单线程适用于简单小游戏(如单机打靶),所有任务由主线程顺序处理,代码简单但效率较低;多线程则适合复杂场景(如多人在线3D大作),通过渲染、逻辑、网络、音效等线程分工协作,确保画面流畅、响应迅速和实时同步。选择依据取决于游戏复杂度、联网需求和性能要求,小型游戏用单线程,大型高要求项目必须采用多线程架构。(149字) 阅读详情

本文有点长,建议分开食用。本文可以看做是介绍进程的一些特性,也可以看做是对进程描述符的各个重要字段的介绍。

1. 什么是进程

进程就是程序执行的一个实例。进程在创建时执行和父进程相同的代码,但是拥有自己的独立的数据拷贝(堆栈)。

所以,进程可以看做一个分配系统资源的实体。系统资源包括CPU时间、内存。

在linux源代码里,进程可以称之为task,也可以称之为thread。所以内核代码里看到这两个单词,都是在描述进程信息。

2. 轻量级进程与线程

线程thread就是进程的一个执行流,一个进程可以有多个执行流。所以说现代UNIX系统中,一个进程可以由多个线程组成。

假定我们正在执行一个聊天程序,这个聊天程序就是一个进程,那它至少要有两个执行流:一个负责响应用户的操作,比如说输入消息到聊天窗口,一个负责监听用户好友发来的消息。

那么显然这个聊天程序是一个多线程进程。那么这就造成一个问题:如果在内核中,把这个多线程的程序也当做是普通进程来执行,执行流的调度都发生在用户态,那么当用户操作聊天窗口的时候,监听消息的执行流就是阻塞状态,得不到执行。

所以,我们期待的是CPU以线程为单位进行调度。linux使用了轻量级进程,所谓轻量级进程就是相互之间可以共享某些资源的进程,轻量级进程和线程具有对应关系。一个多线程程序,内核用一个线程组来处理它。

面试中经常会问到进程和线程的区别,这里可以看出来一个重要的区别就是:进程是资源分配的基本单位,线程是调度的基本都单位。

3. 描述一个进程(x86_86)
struct task_struct {
	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
	struct thread_info *thread_info;
	atomic_t usage;
	unsigned long flags;	/* per process flags, defined below */
	unsigned long ptrace;

	int lock_depth;		/* Lock depth */

	int prio, static_prio;
	struct list_head run_list;
	prio_array_t *array;

	unsigned long sleep_avg;
	long interactive_credit;
	unsigned long long timestamp;
	int activated;

	unsigned long policy;
	cpumask_t cpus_allowed;
	unsigned int time_slice, first_time_slice;

	struct list_head tasks;
	struct list_head ptrace_children;
	struct list_head ptrace_list;

	struct mm_struct *mm, *active_mm;

/* task state */
	struct linux_binfmt *binfmt;
	int exit_code, exit_signal;
	int pdeath_signal;  /*  The signal sent when the parent dies  */
	/* ??? */
	unsigned long personality;
	int did_exec:1;
	pid_t pid;
	pid_t __pgrp;		/* Accessed via process_group() */
	pid_t tty_old_pgrp;
	pid_t session;
	pid_t tgid;
	/* boolean value for session group leader */
	int leader;
	/* 
	 * pointers to (original) parent process, youngest child, younger sibling,
	 * older sibling, respectively.  (p->father can be replaced with 
	 * p->parent->pid)
	 */
	struct task_struct *real_parent; /* real parent process (when being debugged) */
	struct task_struct *parent;	/* parent process */
	struct list_head children;	/* list of my children */
	struct list_head sibling;	/* linkage in my parent's children list */
	struct task_struct *group_leader;	/* threadgroup leader */

	/* PID/PID hash table linkage. */
	struct pid_link pids[PIDTYPE_MAX];

	wait_queue_head_t wait_chldexit;	/* for wait4() */
	struct completion *vfork_done;		/* for vfork() */
	int __user *set_child_tid;		/* CLONE_CHILD_SETTID */
	int __user *clear_child_tid;		/* CLONE_CHILD_CLEARTID */

	unsigned long rt_priority;
	unsigned long it_real_value, it_prof_value, it_virt_value;
	unsigned long it_real_incr, it_prof_incr, it_virt_incr;
	struct timer_list real_timer;
	struct list_head posix_timers; /* POSIX.1b Interval Timers */
	unsigned long utime, stime, cutime, cstime;
	unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw; /* context switch counts */
	u64 start_time;
/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
	unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
/* process credentials */
	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;
/* limits */
	struct rlimit rlim[RLIM_NLIMITS];
	unsigned short used_math;
	char comm[16];
/* file system info */
	int link_count, total_link_count;
	struct tty_struct *tty; /* NULL if no tty */
/* ipc stuff */
	struct sysv_sem sysvsem;
/* CPU-specific state of this task */
	struct thread_struct thread;
/* filesystem information */
	struct fs_struct *fs;
/* open file information */
	struct files_struct *files;
/* namespace */
	struct namespace *namespace;
/* signal handlers */
	struct signal_struct *signal;
	struct sighand_struct *sighand;

	sigset_t blocked, real_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;
	
	void *security;

/* Thread group tracking */
   	u32 parent_exec_id;
   	u32 self_exec_id;
/* Protection of (de-)allocation: mm, files, fs, tty */
	spinlock_t alloc_lock;
/* Protection of proc_dentry: nesting proc_lock, dcache_lock, write_lock_irq(&tasklist_lock); */
	spinlock_t proc_lock;
/* context-switch lock */
	spinlock_t switch_lock;

/* journalling filesystem info */
	void *journal_info;

/* VM state */
	struct reclaim_state *reclaim_state;

	struct dentry *proc_dentry;
	struct backing_dev_info *backing_dev_info;

	struct io_context *io_context;

	unsigned long ptrace_message;
	siginfo_t *last_siginfo; /* For ptrace use.  */
};

以上就是2.6内核源码中进程描述符task_struct的定义。描述符下面的字段很多,大概可以看到,一个进程有它的状态、有自己的parent,有对应的内存空间mm,信号signal_struct,文件files_struct等等。接下来就根据这些字段,介绍进程的一些比较重要的静态特性。

4. 进程的资源限制

对应的字段是struct rlimit rlim[RLIM_NLIMITS];大概限制了进程可以拥有的地址空间,CPU最长时间,可以打开的最大文件大小,等等。

5. 进程关系

可以是亲属关系,也有非亲属关系,对应的字段是:

	struct task_struct *real_parent; /* real parent process (when being debugged) */
	struct task_struct *parent;	/* parent process */
	struct list_head children;	/* list of my children */
	struct list_head sibling;	/* linkage in my parent's children list */
	struct task_struct *group_leader;	/* threadgroup leader */

亲属关系,一个进程有它的父亲,儿子,和兄弟。所谓real_parent和parent,是当进程被另一个进程监控追踪时,它的parent指针会改变,而real_parent指针总是指向创建这个进程的进程。

前面提到了线程组,当这个进程是线程组的一员时,需要一个指针指向线程组的leader。

6. thread_info

进程描述符是放在动态内存中的。此外,内核每处理一个进程,都会分配一个2页的空间,单独存放2个内容,一个是进程描述符的thread_info字段,一个是该进程的内核态堆栈。thread_info在x86_64中长这样:

struct thread_info {
	struct task_struct	*task;		/* main task structure */
	struct exec_domain	*exec_domain;	/* execution domain */
	__u32			flags;		/* low level flags */
	__u32			status;		/* thread synchronous flags */
	__u32			cpu;		/* current CPU */
	int 			preempt_count;

	mm_segment_t		addr_limit;	
	struct restart_block    restart_block;
};

看到thread_info里也有个task指针,就能明白task和thread_info是一一对应的。

内核分配给进程的2页的空间,除去thread_info占用的之外,剩下的都是堆栈区。那么这片区域也可以这么表示:

union thread_union {
	struct thread_info thread_info;
	unsigned long stack[2048];
};

这片区域里,thread_info从低地址开始,stack从高地址开始向下增长,栈顶的地址存放在esp寄存器之中。栈里每写入一行数据,esp就会自减。

7. current

current是内核代码里的一个宏,用来指向当前正在处理的进程。它的原理是根据esp的值得到thread_info的首地址,因为他们都在一个连续的2页的空间内。假设是32位地址系统,thread_union就是2048*sizeof(unsigned long) = 2^13字节,所以屏蔽掉esp值的低13位就得到了thread_union的首地址,也就是thread_info的地址。thread_info的地址也就是thread_info.task的地址。

8. pid和tgid

每个进程描述符还有一个自己的pid。这个pid在创建进程的时候由系统分配,系统维护着一个pidmap_array位图,用这个来查找当前可用的pid。

	pid_t pid;
	pid_t __pgrp;		/* Accessed via process_group() */
	pid_t tty_old_pgrp;
	pid_t session;
	pid_t tgid;

另外,每个进程描述符里还有个tgid的字段,这是希望对线程组中的轻量级进程进行取pid操作时(getpid()),可以直接返回其所在线程组的领头线程的pid,而不是它真实的pid(当然了,如果这个线程就是领头线程,那它的pid=tgid)。

这保证了系统在操作一个进程的时候可以把它对应的整个线程组都操作到,比如kill()的时候。

系统中有一个全局变量叫pid_hash。

static struct list_head *pid_hash[PIDTYPE_MAX];

它包含4个hash表,分别保存了所有的pid,所有的线程组领头进程的pid,所有的进程组领头进程的pid,所有的会话领头进程的pid。

(*进程组:比如在shell里敲一个ls | sort | more命令,就为ls,sort和more这三个进程创建了一个进程组,这三个进程一起表示一种job的抽象)

9. 进程链表
struct list_head tasks;

进程描述符里这个字段,让所有进程都在一个双向链表上,这个链表的开端是个全局变量init_task,它指向swapper进程的描述符。所以内核里可以以init_task描述符为起始,遍历到当前存在的所有进程。

#define for_each_process(p) \
	for (p = &init_task ; (p = next_task(p)) != &init_task ; )
10. 运行链表和优先级队列
	int prio, static_prio;
	struct list_head run_list;
	prio_array_t *array;

内核在执行的时候,会发生进程调度,当前运行的进程让出cpu,换上来一个新进程。这个进程必须是可运行状态的,怎么快速找到一个可运行状态的进程呢?每个进程描述符都有一个run_list字段,把这个进程挂在一个可运行队列上。进程拥有静态优先级static_prio和动态优先级prio。其中动态优先级影响进程调度时调度策略的选择。它的取值范围是[0, 139]。

进程描述符下还有一个指针array指向一个prio_array_t结构,看prio_array_t这个结构体:

typedef struct prio_array {
	int nr_active;
	unsigned long bitmap[5];
	struct list_head queue[140];
}prio_array_t;

array->queue[1]就表示一个优先级为1的队列,里面每个节点都是一个优先级为1的进程。

11. 进程状态

那么怎么表示一个进程是可运行状态还是不可运行呢?进程描述符里有一个state字段。它的取值包括TASK_RUNNING,TASK_INTERRUPTIBLE,TASK_UNINTERRUPTIBLE,TASK_STOPPED,TASK_TRACED,EXIT_ZOMBIE等。

其实run_list里挂的就是一些状态为TASK_RUNNING的进程。而在等待状态中的进程则是TASK_INTERRUPTIBLE或者TASK_UNINTERRUPTIBLE的。


12. 等待队列

我们知道RUNNING状态的进程有自己的单独队列,那么其他状态的进程呢?

僵尸状态和暂停状态的进程,访问简单,直接通过pid找就行了,不需要单独建立队列。

等待状态(TASK_UNINTERRUPTIBLE或者TASK_INTERRUPTIBLE)的进程,是需要单独建立一个等待队列的。等待队列表示一组睡眠的进程,当某个条件发生时,就会唤醒其中的进程。

等待队列的头结点定义如下:

struct __wait_queue_head {
	spinlock_t lock;
	struct list_head task_list;
};
typedef struct __wait_queue_head wait_queue_head_t;

等待队列的元素定义如下:

struct __wait_queue {
	unsigned int flags;
	struct task_struct * task;
	wait_queue_func_t func;
	struct list_head task_list;
};

一个等待队列的元素,除了指向进程描述符之外,还有func字段,指向唤醒时要执行的函数。flags字段表示这个进程是互斥进程(flags=1)还是非互斥进程(flags=0)。互斥进程相互之间竞争同一个互斥资源,所以在唤醒的时候一次只能唤醒一个,而非互斥进程没这个限制,唤醒时会把等待队列里的所有进程都唤醒。

把一个进程加入等待队列的方法有很多,这里只介绍一个把当前进程current加入等待队列q的函数sleep_on():

#define	SLEEP_ON_VAR				\
	unsigned long flags;			\
	wait_queue_t wait;			\
	init_waitqueue_entry(&wait, current);

#define SLEEP_ON_HEAD					\
	spin_lock_irqsave(&q->lock,flags);		\
	__add_wait_queue(q, &wait);			\
	spin_unlock(&q->lock);

#define	SLEEP_ON_TAIL						\
	spin_lock_irq(&q->lock);				\
	__remove_wait_queue(q, &wait);				\
	spin_unlock_irqrestore(&q->lock, flags);
void sleep_on(wait_queue_head_t *q)
{
	SLEEP_ON_VAR

	current->state = TASK_UNINTERRUPTIBLE;

	SLEEP_ON_HEAD
	schedule();
	SLEEP_ON_TAIL
}

过程就是初始化一个指向当前进程的wait_queue_t,然后加入等待队列q,schedule(),当被唤醒时再把这个wait_queue_t从q中移出。

当某个条件为真的时候,就调用wake_up函数把队列q唤醒。过程是遍历q,调用wait_queue_t.func唤醒,直到队列空或者唤醒了一个互斥进程。

(在等待队列中,非互斥进程总是在队列前面,互斥进程总是在队列尾部。当然,一个等待队列里既有非互斥进程又有互斥进程的情况并不常见。)

13. 总结

本文介绍了什么是进程,线程和轻量级进程,并概括介绍了2.6内核代码中的进程描述符。

进程具有自己的状态,内存空间,打开的文件等一系列属性,进程具有父子兄弟,进程在执行时会有一个2页的内存空间用来存放自己的thread_info描述符和堆栈,栈顶的地址被写在esp寄存器中,内核可以通过读取esp寄存器中的值,倒推出thread_info的地址,进而得到当前执行的进程的描述符的地址(用current代表)。

除了通过current取到当前执行的进程外,系统要找到一个进程,第一可以通过pid,内核里定义了4个pid_hash。第二,所有进程都通过tasks字段挂在了一起,首进程(swapper)的描述符被写在全局变量init_task中,系统可以通过init_task.tasks.next遍历完所有的进程。

另外,所有可运行状态的进程都处在某个优先级的运行队列上,等待状态的进程也会存在于一个等待队列上。

第8讲:基于CST PCB Studio的电源完整性仿真(IR Drop + PDN) 本文系统介绍了电源完整性(PI)仿真的两大核心模块:直流IRDrop仿真与交流PDN阻抗仿真。文章详细阐述了两种仿真的原理、算法(PEEC和3DFE-FD)及完整操作流程,包括参数配置、软件实操步骤和常见问题解决方案。IRDrop仿真用于分析直流供电压降问题,PDN仿真则针对高频电源噪声和谐振问题。文中还提供了优化建议和故障排查方法,如调整铜箔厚度、优化电容布局等,为高速数字系统的电源完整性设计提供了全面的技术指导。(149字) 阅读详情

相关推荐

Polyworks脚本开发学习笔记(十五)-用Python连接Polyworks的COM组件

Polyworks脚本开发学习笔记(十五)-利用Python连接Polyworks的COM组件

qq_43662503的博客 2501

进程管理(四)--linux进程描述符task_struct

Linux内核涉及到进程和程序的所有算法都围绕一个名为task_struct的数据结构建立,对于Linux内核把所有进程的进程描述符task_struct数据结构链成一个单链表(task_struct->tasks),该数据结构定义在include/sched.h中。这是系统的中主要的一个数据结构,其进程管理task_struct的结构图如下 1 任务ID 每一个任务都应用有一个ID,作为这个任务的唯一标识。pid是进程的ID,tgid是线程的group ID,group_leader是进程组的组长

奇小葩 2559

JavaFx之集成FontAwesomeFX与JFoenix(十五)

本文详细介绍了如何在JavaFx项目中同时集成JFoenix和FontAwesomeFX,以创建现代化、美观的桌面应用界面。通过Maven依赖配置、动态代码创建和FXML静态声明两种方式,演示了如何将JFoenix的Material Design控件与FontAwesomeFX的丰富矢量图标完美结合,并提供了实战案例展示如何构建一个功能完善的现代化工具栏。

pepsi的博客 437

__set_current_state

/cpu运行队列中删除任务。

wmzjzwlzs的专栏 713

动态数据脱敏技术分析

在当前国内信息安全热潮中,数据脱敏作为数据安全的重要一环得到了业界的认可与重视。早在2012年,数据脱敏首次作为一个单独的魔力象限由Gartner发布,Gartner在2014年又提出了:按照数据使用场景,将数据脱敏分为静态数据脱敏(Static data masking-SDM )与动态数据脱敏(Dynamic data masking-DDM )。 可能有人望文生义,认为动态数据脱敏一定比静态数据脱敏高级。非也非也,静态or动态,取决于脱敏的使用场景,主要是以使用场景为由来选择合适的数据脱敏的模式。 本

美创科技的博客 4670

【无标题】ReaxFF拟合参数以及算法安装

ReaxFF拟合参数以及算法安装

zmzyzm的博客 1418

linux获取当前进程进程号,Linux内核获取当前进程结构的current宏

上篇文章Linux内核的源码结构简介(1)简单介绍了Linux内核源码的目录结构,以及和进程的task_struct的几个关键变量,最后提到了在内核里获取当前进程的pid的代码:current->pid。current,属于内核的一个宏,指向get_current()函数。#define current get_current()所以代码current,实际是获取get_current()函...

weixin_31440053的博客 2672

用简单仿真链路产生 WiFi CSI(不依赖专用工具箱,matlab实现)

这篇文章详细介绍了使用MATLAB仿真生成WiFi信道状态信息(CSI)的过程。内容包括:准备工作(定义OFDM和MIMO参数)、基本参数设置(天线数、FFT点数等)、构造训练OFDM符号、多径瑞利信道建模、逐天线时分发射接收处理、CSI信道估计方法,以及幅值和相位的可视化。通过BPSK调制和瑞利衰落信道仿真,实现了简单的CSI生成流程,为初学者理解CSI产生机理提供了直观指导。文章强调这仅是基础仿真,更深入的研究需要实际数据采集。文末还提供了WiFi指纹定位的相关参考资料。

静水流深,沧笙踏歌 1205

linux中pid gid tgid tid的区别和联系

    https://blog.youkuaiyun.com/techtitan/article/details/39134927 getpid : 取得process id,对于thread,就是取得线程对应进程的id; 对应的system call:  asmlinkage long sys_getpid(void) 1614 { 1615         return current->t...

hunter 2343

【汽车ECU电控数据管理篇】A2L文件在ECU标定中的关键作用与实战解析

本文深入解析A2L文件在汽车ECU标定中的关键作用,详细介绍了其作为'数据字典'的核心功能与实战应用。通过剖析A2L文件的结构、关键标签及常见问题,帮助工程师高效管理电控数据,提升ECU标定效率与准确性。文章特别强调了ASAP2标准下的A2L文件在汽车电控系统中的重要性。

a3b4c5的博客 787

【华为OD机试真题】65、高矮个子排队 | 机试真题+思路参考+代码解析 (C++、Java、Py、C语言、JS)

题目描述 >现在有一队小朋友,他们高矮不同,我们以正整数数组表示这一队小朋友的身高,如数组{5,3,1,2,3}。 >  我们现在希望小朋友排队,以"高" "矮" "高" "矮" 顺序排列,每一个高位置的小朋友要比相邻的位置高或者相等;每个 "矮" 位置的小朋友要比相邻的位置矮或者相等; >  要求小朋友们移动的距离和最小,第一个从“高"位开始排,输出最小移动距离即可。 >  例如,在示范小队{5,3,1,2,3}中, {5, 1, 3, 2, 3}是排序结果。 > 

KJ.JK 2098

线程问题——同样的程序,在ubuntu中运行和嵌入式中PID表现不同的原因

1. 同一多线程程序,经过编译和交叉编译后,在ubuntu和在我们的ARM板的嵌入式LINUX中运行时候,通过ps 看到的信息不一致:    比如:同样的attr_thread这个程序:    ubuntu中运行后,通过ps -aux只能看到一个进程在运行    目标板中运行后,通过ps 能看到4个进程在运行,但运行的程序名字是一致的 原因:    ubuntu中使用NPTL线程库,目标

hare_Lee的专栏 2866

构建具有预测维护能力的AI Agent

随着工业4.0的推进,工业设备的复杂性和自动化程度不断提高,设备的稳定运行对于企业的生产效率和经济效益至关重要。预测维护作为一种先进的设备维护策略,能够通过对设备状态的实时监测和分析,提前预测设备故障,从而避免设备意外停机,降低维护成本。本文的目的是详细阐述如何构建具有预测维护能力的AI Agent,涵盖从数据采集、处理、模型训练到实际应用的整个流程,为企业和开发者提供全面的技术指导。本文将按照以下结构进行组织:首先介绍核心概念与联系,包括预测维护和AI Agent的基本原理和架构;

2501_92132293的博客 943

深入理解Linux内核个人小结3--进程

进程---程序执行的一个实例 一.  进程的静态特性    1.进程与线程:       Linux2.6内核版本支持多线程,现在大部分多线程应用程序都是使用pthread库编写的。  Linux2.6内核加入了对内核线程组的概念,每个进程描述符多加了一个tgid字段。       Linux通过轻量级进程来实现对多线程的支持,线程之间可以共享一些资源(地址空间、打开的文件等)。线

我是小强的专栏 715

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

linux内核回写线程代码分析,深入分析Linux内核源码-第四章 进程描述

深入分析Linux内核源码-第四章 进程描述【摘要】本章详解了task_struct结构,介绍了进程的各种状态,分析了进程的组织形式,针对不同的进程状态介绍了运行队列和等待队列;介绍了通用链表list_head面向对象思想在C中的具体实现,以及在此基础上运行的等待队列机制;最后简单介绍了内核编程的信号量、原子操作以及自旋锁机制。【关键字】task_struct,进程状态,运行队列,等待队列,lis...

weixin_30798713的博客 620

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

数据结构课程设计(一)---系统进程统计(必做)(链表)

不断获取系统中的进程信息,并记录下这些进程的内存使用情况、持续时间等信息,然后对比前后两次获取的进程信息,找出已结束的进程并记录其结束时间和持续时间,把它们存放在。函数用于刷新后更新进程,通过比对当前进程链表和已结束进程链表,找出新的进程并添加到当前进程链表和已结束进程链表中,并通过。函数将当前进程链表和已结束进程链表的信息显示出来,包括进程名、PID、内存使用情况、持续时间和结束时间。来控制字体颜色,当前进程中的信息为绿色,已结束进程中的信息为红色,便于区分。函数创建的已结束进程链表中。

c55555556的博客 844

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Linux之进程

我们当前是在proc里面这个进程PID对应的这个目录里面的,上面说了PID对应的目录是进程创建的时候才会在proc目录下新增的。那如果我们把对应的进程终止(CTRL+c):再想查看这个目录的内容就不行了:上一级目录也回不去了:因为进程终止,操作系统就会在proc目录下把这个进程PID对应的目录及其里面的内容删除掉。所以proc目录里面的内容是动态变化的。当前我再创建一个进程,查看/proc/5194进程目录下的 内容,没什么问题:

ZZY5707的博客 221

linux进程链表,linux中链表_队列等的基本原理以及操作以及堆栈

内核版本为:2.4.10等待队列相关结构体:DECLARE_WAITQUEUE(wait, current); // 定义一个等待队列,和当前进程挂钩#define DECLARE_WAITQUEUE(name, tsk) wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)#define __WAITQUEUE_INITIALIZER(na...

weixin_42347375的博客 353

【linux内核】链表

重点介绍linux使用的链表,其他几种看图简单理解,linux 链表采用数据和链表分开形式的环形双向链表。本次实验采用linux下模块注册的形式进行,注册后会把链表数据打印到终端。单向链表双向链表环形链表。

qq_42427720的博客 332

进程间链表实现

《老酒馆》 ​对比起,踩您脚了; 老二两:是我对不起您,耽误您脚落地了。 隔离在家,第四天。2021年8月2日13:13:02。 --共享内存-- 在文章《mmap从低向高增长的legacy模式和从高向低增长的modern模式》我介绍过进程地址空间的内存布局,当不同的进程同时映射一个文件到自己的进程地址空间时,就可以实现进程间的共享内存。 对于内存文件映射的整体架构如下图: --链表-- 拿单链表为例,链表节点的next域保存了链表的下一个节点的虚...

RToax 690

操作系统之进程

一.进程的描述 1.进程的定义 (1)进程是程序的一次执行 (2)进程是一个程序及其数据在处理机上的顺序执行时所发生的活动 (3)进程是具有独立功能的程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立的单位 综上所述,进程就是进程实体的运行过程,是系统进行资源分配和调度的一个独立的单位 2.进程的特点 进程具有程序没有的PCB结构(进程控制块) (1)动态性 它...

jch_120312的博客 553

进程(3)

linux系统中进程的组织方式          一个系统中通常可以有数百个数千个进程,相应的也就有这么多的PCB,必须使用一些适当的方式将这些PCB组织起来。进程的组织方式其实大都是数据结构中数据的组织方式。          进程链表:双向循环链表将进程联系起来          struct task_struct          {               stru

yangliuhepanpan的专栏 339

Linux内核链表使用方法

Linux内核链表使用方法介绍

hinewcc的博客 2281

【Linux】静态进程和动态进程

如果独立性和部署简便性是首要考虑的因素,且对空间要求相对较低,可以选择静态进程。如果对空间要求敏感,需要多个程序共享相同库,或者需要频繁更新和修复程序,可以选择动态进程。在实际应用中,可以根据具体项目需求综合考虑这些因素,选择最适合项目的加载方式。无论选择静态进程还是动态进程,了解它们的特点以及在不同情况下的适用性,可以帮助开发者更好地优化程序的性能和管理。

double222222的博客 2430

【Linux系统】进程PCB链表节点结构的真相:内置链式节点

本文讲解:Linux系统中,进程PCB会内置链表节点,而不是PCB本身设计成链表节点,使其可以同时存在于不同的链式队列中(运行队列、等待队列),增加了可拓展性与优雅程度

从不依靠,从不寻找,非常沉默,非常骄傲。 你必须非常努力,才能看起来毫不费力。 1201

linux的几个链表

1. 进程链表: 连接所有进程(双向),头: init_task,  节点: task_struct中的tasks; 2. TASK_RUNNING状态的进程链表:是每cpu变量(因为runqueue是每cpu变量),方便cpu选择task, 优先级队列(140级),头:run

brucexu1978的专栏 726
上一篇: Linux的内存寻址——浅谈分段和分页机制
下一篇: 浅谈linux进程的切换
HelloNerd
博客等级 码龄12年 10粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值