Linux学习_系统进程概念

系统进程概念

一、进程的概念和结构

1.概念:

  • 程序:程序是存放在磁盘文件中的可执行文件
  • 进程:
    • 程序的执行实例被称为进程(process)
    • 进程具有独立的权限与职责。如果系统中某个进程崩溃,他不会影响到其余进程。
    • 每个进程运行在各自的虚拟地址空间中,进程之间可以通过由内核控制的机制相互通信。
  • 进程ID
    • 每个linux进程都一定有一个唯一的数字标识符,称为进程ID(process ID),进程ID总是一个非负整数。

linux内核中的文件:文件描述符表->文件表项->i节点->外部硬盘
进程在内核当中的结构:

/usr/src/linux-headers/include/linux/sched.h

task_struct

二、进程的启动,终止,查看,状态,调度

1.C语言的启动

  • 内核启动特殊例程

  • 启动例程

    • 在进程的main函数执行之前内核会启动
    • 该例程放置在/lib/libc.so.***中
    • 编译器在编译时会将启动例程编译进可执行文件中
  • 启动例程作用

    • 搜集命令行的参数传递给main函数中的atgc和argv
    • 搜集环境信息构建环境表并传递给main函数 (带参main的第三个形参,一般不用)
    • 向内核登记进程的终止函数
      2.C语言的终止
  • 正常终止

    • 从main函数返回
    • 调用exit (标准c库函数)
    • 调用_exit或_Exit (系统调用)
    • 最后一个线程从其启动例程返回
    • 最后一个线程调用pthread_exit
  • 异常终止

    • 调用abort
    • 接受到一个信号并终止(比如段错误信号)
    • 最后一个线程对取消请求做处理响应
  • 进程返回

    • 通常程序运行成功返回0,否则返回非0
    • 在shell中可以查看进程返回值(echo $?)

3.atexit函数

#include <stdlib.h>
int atexit(void (*function)(void));
返回:若成功则为0,若出错则为-1
功能:向内核登记终止函数
  • 每个启动的进程都默认登机了一个标准的终止函数
  • 终止函数在进程终止时释放进程所占用的一些资源
  • 登记的多个终止函数执行顺序是以栈的方式执行,先登记的后执行

示例:

#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

//定义进程的终止函数
void term_fun1(void)
{
	printf("first term func\n");
}

void term_fun2(void)
{
	printf("second term func\n");
}

void term_fun3(void)
{
	printf("third term func\n");
}

int main(int argc, char argv[])
{
	if(argc<3)
	{fprintf(stderr,"usage:%s file [exit|_exit|return]\n",argv[0]);exit(1);}
	
	//向内核登记终止函数,以栈方式存储FILO,在函数结束(比如运行return,exit函数)的时候会调度运行
	atexit(term_fun1);
	atexit(term_fun2);
	atexit(term_fun3);
	
	FILE* fp = fopen(argv[1],"w");
	fprintf(fp,"hello"); //全缓存,当缓存全满才一次性写入文件里边
	if(! strcmp(argv[2],"exit") )exit(0);
	else if(! strcmp(argv[2],"_exit") )_exit(0);//特别的这个不会运行atexit,也不会清除缓存
	else if(! strcmp(argv[2],"return") )return 0;
	else fprintf(stderr,\
	"usage:%s file  [exit|_exit|return]\n",argv[0]);
}

4.进程终止方式区别

-|return|exit()|_exit()/_Exit()|
是否刷新标准I/O内存|是|是|否
是否自动调用终止函数|是|是|否

  • _exit()/_Exit()是直接和内核连接的,exit()源码中是使用_Exit()结束的

5.查看系统中的进程

  • ps指令:
    • 通常可以看到:进程的ID、进程状态和进程的Command
$ps -ef | more	 #查看后台信息

$ps -aux | more	 #查看进程占CPU、内存多少空间

ps输出信息:

USER|进程属主
PID|进程的ID
PPID|父进程
%CPU|进程占用的CPU百分比
%MEM|占用内存的百分比
NI|进程的NICE值,数值大,表示较少占用CPU
VSZ|进程虚拟大小
RSS|驻留中页的数量
TTY|终端ID
WCHAN|正在等待的进程资源
START|启动进程的时间
STAT|进程的状态
TIME|进程消耗CPU的时间
COMMAND|命令的名称和参数

6.进程状态 STAT

  • 运行状态
    • 系统当前进程
    • 就绪状态进程
    • ps命令的STAT列 为值R (Run)
  • 等待状态
    • 等待事件发生
    • 等待系统资源
    • 可中断和不可中断等待态
    • ps命令的STAT列 为值S (Sleep)
  • 停止状态
    • 阻塞,挂起
    • ps命令的STAT列 为值T
  • 僵尸状态
    • 进程终止或结束
    • 在进程表项中仍有记录
    • ps命令的STAT列 为值Z (Zombi)

7.进程调度

  • 第一步:处理内核中的工作
  • 第二步:处理当前进程
  • 第三步:选择进程
    • 实时进程
    • 普通进程
  • 第四步:进程交换

task_struct中的调度信息:

  • 策略
    • 轮流策略
    • 先进先出策略
  • 优先权
    • jiffies变量
  • 实时优先权
    • 实时进程之间
  • 计数器

8.进程状态变化关系

三、进程编程

1.进程标识

/*
#include <unistd.h>
#include <sys/types.h>
pid_t getpid(void);	//获得当前进程ID
uid_t getuid(void);	//获得当前进程的实际用户ID
uid_t geteuid(void);	//获得当前进程的有效用户ID
gid_t getgid(void);	//获得当前进程的用户组ID
pid_t getppid(void);	//获得当前进程的父进程ID
pid_t getpgrp(void);	//获得当前进程所在的进程组ID
pid_t getpgid(pid_t pid);	//获得进程ID为pid的进程所在的进程组ID
*/

#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv)
{
	printf("pid:%d\n",getpid());
	printf("ppid:%d\n",getppid());
	printf("uid:%d\n",getuid());
	printf("euid:%d\n",geteuid());
	printf("user gid:%d\n",getgid());	//用户组id
	printf("gid:%d\n",getpgrp());	//进程组id
	printf("pgid:%d\n",getpgid(getpid()));
	printf("ppgid:%d\n",getpgid(getppid()));
	return 0;
}

将实际用户的权限提升为超级用户root,他的euid为0

$sudo chown root.root process_id	#修改用户权限
$sudo chmod u+s process_id 	#s为粘着位,作用为修改当前用户的有效用户
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值