Linux-----进程(多任务)

一、什么是进程

(一)进程的含义?

进程是一个程序执行的过程,会去分配内存资源,cpu的调度

(二)进程分类:

1、交互式进程

2、批处理进程 shell脚本

3、 守护进程

(三)进程与程序的区别

1)程序是永存,进程是暂时的

2)进程有程序状态的变化,程序没有

3)进程可以并发,程序无并发

4)进程与进程会存在竞争计算机的资源

5)一个程序可以运行多次,变成多个进程

一个进程可以运行一个或多个程序

(四)进程的作用:

并发并行(各执行各的)

(五)进程的状态:

3个状态,就绪→执行态→阻塞(等待,睡眠)基本操作系统

linux中的状态,运行态,睡眠态,僵尸态,暂停态。

(1)运行态(running):进程占有处理器正在运行。

(2)就绪态(ready):进程具备运行条件,等待系统分配处理器以便运行。

(3)阻塞态(blocked):又称为或睡眠(sleep)态,指进程不具备运行条件,正在等待某个事件的完成。

(4)僵尸态(zombie):子运行完,父没运行完,子进程会以终止状态保持在进程表中,并且会一直在等待父进程读取才能退出。

(5)孤儿态:父运行完,子没运行完,子处于托管状态,加重系统负担

(6)创建态:进程正在被创建,但尚未转到就绪态。

(7)终止态:进程已经完成执行并准备被撤销。

cpp 复制代码
进程的状态:

PROCESS STATE CODES
       Here are the different values that the s, stat and state output specifiers 
	   (header "STAT" or "S") will display to describe the state of a process:

               D    uninterruptible sleep (usually IO) //不可中断的睡眠态
               R    running or runnable (on run queue) // 运行态
               S    interruptible sleep (waiting for an event to complete)//可中断的睡眠态
               T    stopped by job control signal      // 暂停态
               t    stopped by debugger during the tracing
               W    paging (not valid since the 2.6.xx kernel)
               X    dead (should never be seen)
               Z    defunct ("zombie") process, terminated but not reaped by its parent

       For BSD formats and when the stat keyword is used, additional characters may be displayed:

               <    high-priority (not nice to other users)
               N    low-priority (nice to other users)
               L    has pages locked into memory (for real-time and custom IO)
               s    is a session leader
               l    is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
               +    is in the foreground process group

     R  --- 运行态 
	 D  --- 不可中断 睡眠态
	 S  --- 可中断 睡眠态 
	 T  --- 暂停态 
	 Z  --- 僵尸态 
cpp 复制代码
cb
struct task_struct {
    PID,             //进程标识符
	PPID,            //父进程ID号  parent 
	当前工作路径     //chdir
	umask            //0002
	进程打开的文件列表 //文件IO中有提到
	信号相关设置       //处理异步io, ---段错误
	用户id,组id
	进程资源的上限
}

二、进程管理的命令

1、top //类似Windows的下任务管理器

2、ps -eLf | head -1 //可以观察到 PID PPID

3、ps -eLf | grep a.out //查看a.out 信息 //可以观察到 PID PPID

4、ps -aux | grep a.out //可以查看进程 的状态

5、pstree //进程树

6、pstree -sp pid号 //查看指定的进程的关系

7、kill //给进程发信号 //kill -l //查看可以发送的信号

操作:

将子进程杀死 。结束子进程,父进程还在,但是父进程并没有对子进程"收尸"

操作:

将父进程杀死 。子进程 还在 ,父进程不在 ---- 孤儿进程

---- 此时由init进程 收养

特殊:

孤儿进程

子进程 还在,父进程不在

僵尸进程

子进程 结束,父进程还在,且父进程并未"收尸"

僵尸态进程有危害

三、函数

pid_t fork(void);

功能:

创建子进程 (通过复制调用进程)

参数:

void

返回值:

成功

在父进程中 返回子进程的pid号

在子进程中 返回0

失败

-1 && errno 被设置

pid号:

pid 本质上就是一个数值

正整数 1

cpp 复制代码
#include<stdio.h>
#include<unistd.h>

int main(int argc, const char *argv[])
{
	pid_t pid = fork();

	if(pid<0)
	{
		perror("fork fail");
		return -1;
	}
while(1)
{
	if(pid > 0)
	{
		printf("hello\n");
	}else if(pid ==0)
	{
		printf("world\n");
	}
}
	
	return 0;
}

1、子进程先运行和是父进程先进程,顺序不确定。

变量不共享。

2、子进程复制父进程的0到3g空间和父进程内核中的PCB,但id号不同。

3、此时,父子进程各自拥有独立的4g内存空间 (32位的系统)

4、功能

通过该函数可以从当前进程中克隆一个同名新进程。

克隆的进程称为子进程,原有的进程称为 父进程。

子进程是父进程的完全拷贝。

复制之后,

子进程和父进程 各自拥有自己的 用户空间(进程空间)

子进程和父进程的执行过程是从fork函数之后执行。

子进程与父进程具有相同的代码逻辑。

5、返回值:int 类型的数字。

在父进程中:成功 返回值是子进程的pid号 >0

失败 返回-1;

在子进程中:成功 返回值 0

失败 无

6、注意:

1.创建好之后,父子进程的运行顺序是不确定 ---全部取决于 操作系统的调度

注意:

1.父子进程创建好之后,各自拥有独立4G内存空间(32位系统)

2.他们的数据相互独立,父进程或子进程对数据的修改,不会相互影响,只会对各自造成影响

(一)、练习

如果两次fork同时前后执行,会生成几个进程?

fork();

fork();

他们之间的关系如何表示,

有多少个子进程,

有没有孙进程?

2、fork()&&fork()||fork(); //总共几个进程

cpp 复制代码
#include<stdio.h>
#include<unistd.h>

int main(int argc, const char *argv[])
{
	fork()&&fork()||fork();
	while(1);
		sleep(1);	
	return 0;
}

3、练习:

自己分别定义一个 static的变量 static int a = 0;

全局变量 int b = 1;

堆区 int *p = (int *)malloc(sizeof(int));

*p = 2;

(做修改)父进程中 做加1的操作 ,

子进程中做加2的操作

sleep(1);

分别打印,查看效果!

cpp 复制代码
#include<stdio.h>
#include<unistd.h>
#include <stdlib.h>

int main(int argc, const char *argv[])
{
	pid_t pid = fork();
	static int a =0;
	int b = 1;
	int *p = (int *)malloc(sizeof(int));
	*p = 2;

	while(1)
	{
	if(pid > 0)
	{
		a++;
		b++;
		*p++;
		sleep(1);
		printf("father   ");
		printf("a = %d b = %d *p = %d\n",a,b,*p);
	}else if(pid == 0)
	{
		a+=2;
		b+=2;
		*p+=2;
		printf("sun   ");
		printf("a = %d b = %d *p = %d\n",a,b,*p);
		sleep(1);
	}
	}
	return 0;
}

4、创建n个进程 :

输入n 创建n个子进程

cpp 复制代码
#include<stdio.h>
#include<unistd.h>

int main(int argc, const char *argv[])
{
	int n = 0;
	scanf("%d",&n);

	int i = 0;

	 pid_t  pid = 0;
	for(i = 0;i < n;i++)
	{
		pid = fork();

		if(pid < 0)
		{
			perror("fork fail");
			return -1;
		}

		if(pid>0)
		{
			continue;
		}else if(pid == 0)
		{
			break;
		}
	}

	while(1)
		sleep(1);
	return 0;
}

5、创建n个进程,分批复制文件

cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>


void do_copy(int fd_s,int fd_d,int size,int i,int length)
{
	char buf[1024];
	
	//定位到要操作位置 
	lseek(fd_s,i*size,SEEK_SET);
	lseek(fd_d,i*size,SEEK_SET);
	
	int ret = read(fd_s,buf,length);
	write(fd_d,buf,ret);
}


int main(int argc, const char *argv[])
{

    if (argc != 3)
	{
		printf("Usage: %s <src> <dest>\n",argv[0]);
		return -1;
	}

	int n = 0;
	
	printf("Input proccess num:");
	scanf("%d",&n);

	int i = 0;	
	pid_t pid = 0;
	 
	for (i = 0; i < n;++i)
	{
		pid = fork();

		if (pid < 0)
		{
			perror("fork fail");
			return -1;
		}
		if (pid > 0)
		{
			continue;
		}else if (pid == 0)
		{
			break;
		}
	}

	if (pid > 0)
	{
		printf("father exit!\n");
		return 0;
	}else if (pid == 0) 
	{
		int fd_s = open(argv[1],O_RDONLY);
		if (fd_s < 0)
		{
			perror("open fail");
			return -1;
		}
		int fd_d = open(argv[2],O_WRONLY|O_CREAT|O_EXCL,0666);
		if (fd_d < 0)
		{
			if (errno == EEXIST)
			{
				fd_d = open(argv[2],O_WRONLY);
			}else 
			{
				perror("open fail");
				return -1;
			}
		}

		struct stat st;
		if (stat(argv[1],&st) < 0)
		{
			perror("stat fail");
			return -1;
		}
		printf("size = %ld\n",st.st_size);
		
		int size = st.st_size/n; 
		int length = size;
		if (i == n-1)
		{
			length = st.st_size - size*(n-1);
		}
	
		printf("i = %d each size = %d\n",i,size);
		do_copy(fd_s,fd_d,size,i,length);
		close(fd_s);
		close(fd_d);
	}



	return 0;
}
相关推荐
真正的醒悟16 分钟前
H3C交换机&路由器&防火墙FTP/TFTP服务器搭建。
服务器·网络·智能路由器
你好呀我是裤裤1 小时前
Linux基础开发工具的使用(apt、vim、gcc、g++、gdb、make、makefile)
linux·运维·vim
不修×蝙蝠1 小时前
Tomcat理论(Ⅰ)
java·服务器·java-ee·tomcat
望获linux1 小时前
如何在望获实时 Linux & 京博航友善 NanoPC-T6 上部署 Docker
linux·运维·服务器·docker·eureka·开源软件
wangchen_01 小时前
linux编译器和自动化构建工具(gcc与Makeile)
linux·运维·服务器
DC_BLOG1 小时前
Linux-Ansible命令
linux·运维·服务器·ansible
人工干智能1 小时前
科普:“docker”与“docker compose”
运维·docker·容器
suenpeng1 小时前
安全运维,等保测试常见解决问题。
linux·运维·安全
神马都会亿点点的毛毛张1 小时前
【Docker教程】万字长文详解Docker命令
java·运维·后端·docker·容器
贩卖纯净水.1 小时前
REACT学习DAY02(恨连接不上服务器)
服务器·学习·react.js