当前位置:
文档之家› 3-UNIX&Linux操作系统编程-进程与线程
3-UNIX&Linux操作系统编程-进程与线程
files_struct count close_on_exec open_fs fd[0] fd[1] ……
inode f_mode f_pcs f_flags f_count f_owner f_inode f_op f_version file
fd[255]
file operation routines
exit 函数会执行一些特定的清理操作,还会执行标准I/O库的清理 关闭操作(为所有打开流调用fclose函数,这会使得所有缓冲的 输出数据被更新到相应的设备),然后返回内核
exit与return的区别
C语言关键字return与函数exit()在main函数退出 时有相似之处,但两者有本质的区别:
/usr/include/linux/sched.h #define TASK_RUNNING #define TASK_INTERRUPTIBLE #define TASK_UNINTERRUPTIBLE #define TASK_ZOMBIE #define TASK_STOPPED
0 1 2 4 8
2
用户级进程状态切换
收到信号,执行wake_up( ) TASK_RUNNING 就绪状态 唤醒 wake_up( ) 唤醒 wake_up_interruptible()
调度 schedule( )
TASK_UNINTERRUPTIBLE 等待状态(不可中断) schedule( ) sleep_on( )
TASK_INTERRUPTIBLE 等待状态(可中断) schedule( ) interruptible_sleep_on( )
CPU处理运行 syscall_trace( ) schedule( ) sys_exit( ) do_exit( ) TASK_ZOMBIE 僵死状态
TASK_STOP 暂停状态
task_struct:进程状态
进程状态: volatile long state; int exit_state; state成员的可能取值如下: #define TASK_RUNNING 0 #define TASK_INTERRUPTIBLE 1 #define TASK_UNINTERRUPTIBLE #define TASK_ZOMBIE 4 #define TASK_STOPPED 8 exit_state成员的可能取值如下: #define EXIT_ZOMBIE 16 #define EXIT_DEAD 32
task_struct:内存管理
task_struct vm_area_struct vm_end vm_start vm_flags vm_inode vm_ops
process virtual Memory
mm
mm_struct count pgd
data
mmap mmap_avl mmap_sem
调用abort,产生SIGABRT信号
接收到终止信号
终止进程的exit 和_exit 函数
void exit( int status ); /* <stdlib.h> */
void _exit (int status ); /* <unistd.h> */
这两个函数正常地终止一个进程:
_exit 函数将会立即返回内核
3
Linux的进程结构
进程状态(State) 调度信息(Schedule) 标识(Identifiers) 进程间通信(Inter-Process Communication) 时间和定时器(Times and Timers) 文件系统(File system) 。。。。 。。。。 虚拟内存(Virtual memory)
2015-1-5 19
获取进程有效用户号和有效用户组号
头文件unistd.h __uid_t geteuid(void) __uid_t getegid(void)
2015-1-5
20
进程的启动
C程序的启动函数是main
main ( int argc, char *argv[] );
当内核启动一个C程序时,会在调用main函数前 调用特殊的启动函数来获取main函数地址和传递 给main函数的参数,并且将这些信息填写到PCB 中
进程的终止
正常终止
从main返回 调用exit
调用_exit或_Exit
最后一个线程从其启动例程中返回
最后一个线程调用pthread_exit 异常终止
vm_next
vm_end vm_start vm_flags vm_inode vm_ops
code
vm_next
vm_area_struct
task_struct:文件管理
task_struct fs_struct count umask *root *pwd inode
fs files
inode
用于文件存取许可权检查
由exec函数保存
15
进程真实用户号(RUID)
2015-1-5
16
进程真实用户组号(RGID)
创建进程的用户所在的组号为该进程的真实用户组 号(RGID)。可以通过调用getgid()函数来获得当 前进程的真实用户组号。
2015-1-5
人民邮电出版社出版 杨宗德编著
17
return 退出当前函数主体,exit()函数退出当前进程 在main函数中,return 0和exit(0)完成一样的功能 在子函数中,return仅仅从子函数中返回,而调用exit() 将会退出当前进程
2015-1-5
24
atexit及on_exit函数
当进程终止时,程序可能需要进行一些自身的清 理工作,如资源释放等等 atexit及on_exit 函数提供了进行这样工作的机会 ,它允许用户注册若干终止处理函数,当进程终 止时,这些终止处理函数将会被自动调用
Linux的进程组织
进程的物理组织结构
Proc 1 Proc 2 Proc n Proc n+1 Proc n+2
Current
进程的逻辑组织结构
P1
P2
P3
Pn
Pn+1
Pn+2
Pn+3
Pn+4
进程基本属性-进程号与父进程号
2015-1-5
12
Linux
Solaris
进程基本属性-进程组号(PGID)
atexit及on_exit函数
函数原型(std(*func)(void));
int on_exit ( void (*func)( int, void * ), void *arg );
ANSI C规定一个进程最多能注册32个终止处理函 数 调用exit函数终止进程时将会回调这些注册的终止 处理函数(最先注册函数的最后被回调) 调用_exit函数终止进程时将不会回调这些注册的 终止函数
进程组是一个或多个进程的集合。它们与同一作业 相关联,可以接受来自同一终端的各种信号。每个 进程组都有唯一的进程组号,进程组号是可以在用 户层修改的。
2015-1-5
14
进程用户属性
与一个进程相关联的用户ID有如下几种:
进程真实用户号 进程真实用户组号 进程有效有效用户号 进程有效用户组号 设置-用户-ID 设置-组-ID 我们实际是谁(即执行程序或 创建子进程的用户ID)
第三讲:UNIX&Linux进程与线程
内容
UNIX&Linux进程环境及进程属性 UNIX&Linux进程管理及控制 UNIX&Linux线程概念 UNIX&Linux线程控制
进程与程序
程序是一个包含可执行代码的文件,它放在磁盘 等介质上。 当程序被操作系统装载到内存并分配给它一定资 源后,此时可称为进程。 程序是一个静态概念,进程是一个动态概念。
18
普通用户能够修改自己的密码的原因
/etc/passwd文件用来存储所有用户信息,任何用户都可以修改自己的 密码,显然,其它用户在执行/usr/bin/passwd命令时修改了 /etc/passwd文件(并不是说可以使用vi编辑器修改),但是,通过查 看/etc/passwd文件的权限,发现普通用户对此文件仅有读的权限。是 什么原因导致普通用户可以修改/etc/passwd文件呢? 这是因为用户执行“/usr/bin/passwd”命令时,/usr/bin/passwd文件 设置了setuid位,在执行此程序(/usr/bin/passwd)时,该用户所拥 有的权限等同于文件“/usr/bin/passwd”的拥有者root的权限,而root 用户拥有对/ect/passwd文件写的权限,因此普通用户可以通过 /usr/bin/passwd来修改/etc/passwd文件的内容。 如果清除掉“/usr/bin/passwd”文件的setuid权限位,普通用户就不能 修改自己的密码了。
Example: (showtime.c)
#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/times.h>
fprintf(stderr, "User time: %8.3f seconds\n", tinfo.tms_utime/ticks); fprintf(stderr, "System time: %8.3f seconds\n", tinfo.tms_stime/ticks); fprintf(stderr, " child u time: %8.3f seconds\n",tinfo.tms_cutime/ticks); static void showtimes(void) { fprintf(stderr, "Child sys time: %8.3f double ticks; seconds\n", tinfo.tms_cstime/ticks); struct tms tinfo; } } if ((ticks = (double) int main(void) { sysconf(_SC_CLK_TCK)) == -1) perror("Failed to determine clock if (atexit(showtimes)) { fprintf(stderr, "Failed to install ticks per second"); else if (times(&tinfo) == (clock_t)-1) showtimes exit handler\n"); return 1; perror("Failed to get times information"); } else { return 0; }