进程基础概念,fork day32

发布于:2025-07-16 ⋅ 阅读:(16) ⋅ 点赞:(0)

五:进程

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

一:基础定义

PID		进程标识符
当前工作路径   	chdir
umask  	0002
进程打开的文件列表  		文件IO中有提到
信号相关设置 	处理异步io,
用户id,组id
进程资源的上限
ulimit -a,			显示资源上限。
//ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 31598
max locked memory       (kbytes, -l) 65536
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024  //文件默认开1023个
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192	//栈大小,默认8M(8kk)
cpu time               (seconds, -t) unlimited
max user processes              (-u) 31598
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

二:进程和程序的区别

程序:静态 //存储在硬盘中代码,数据的集合
进程:动态 //程序执行的过程,包括进程的创建、调度、消亡

.c ----> a.out-----> process(pid)

1)程序是永存,进程是暂时的
2)进程有程序状态的变化,程序没有
3)进程可以并发,程序无并发

并发:有一个执行体(cpu)同一时刻,多个任务进行
并行:有多个执行体(cpu),多个任务进行

4)进程与进程会存在竞争计算机的资源
5)一个程序可以运行多次,变成多个进程
一个进程可以运行一个或多个程序
内存的分布:0-3G,是进程的空间,3G-4G是内核的空间,虚拟地址(2^32 = 4G)32位系统

ELF||CODE

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(有操作系统才有)虚拟地址 * 物理内存和虚拟内存的地址 映射表 1page=4k mmu 就是4k,4k的分成若干小块

虚拟内存 是计算机系统内存管理的一种技术,它通过软硬件结合的方式,为每个进程提供一个独立且连续的虚拟地址空间(Virtual Address Space),使得进程可以认为自己独占整个内存资源,而实际上物理内存(RAM)可能被多个进程共享或部分数据存储在磁盘上。

三:进程分类/作用/状态

一:分类

​ 1、交互式进程
​ 2、批处理进程 shell脚本
​ 3、 守护进程

二:作用

并发,并行区别。

并发是指在同一时间段内,多个任务交替执行。即使系统只有一个处理单元(如单核CPU),通过快速切换任务,使得多个任务看起来像是同时进行。并发更关注任务之间的调度和协作,强调逻辑上的“同时发生”。例如,一个人轮流吃米饭、蔬菜和牛肉,这就是并发。

并行是指在同一时刻,多个任务真正同时执行。它通常需要多个处理单元(如多核CPU),每个任务在独立的处理单元上运行,互不干扰。并行更关注硬件资源的利用,强调物理上的“同时发生”。例如,两个人同时吃饭,一个吃米饭,一个吃牛肉,这就是并行。
	while (1) {			
		while (1) {
        上下左右
		发视频
		}
	}
三:状态

3个状态,就绪→执行态→阻塞(等待,睡眠)基本操作系统(本质上也是一个链表-队列)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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

file a.out	//详细看对应进程的信息
四:调度
内核主要功能之一就是完成进程调度, 硬件,bios,io,文件系统,驱动
调度算法, other,idle
			rr,fifo  
	实时系统,分时系统(linux)
		rt_thread ucos 
调度逻辑(调度算法):	1.先来先服务
					2.短任务优先
					3.优先级   ->	3.1时间片轮询(分时系统)
--------------------------------------------------------------------	
宏观并行
微观串行(实际就是轮流走,不是一起走)
五:进程相关命令

.ps aux : 功能:查看进程相关信息

ps aux | less : 查看进程信息并通过 less 分页显

​ 1.就绪态、运行态 R
​ 2.睡眠态、等待态
​ 可唤醒等待态 S
​ 不可唤醒等待态 D
​ 3.停止态 T
​ 4.僵尸态 Z
​ 5.结束态

top	//类似window的任务管理器

ps -eLf | head -1	//可以观察到 PID PPID
	UID        PID  PPID   LWP  C NLWP STIME TTY          TIME CMD

  		gerp 	//查找
ps -eLf | grep a.out	//查看a.out
ps -aux | grep a.out //查看进程状态

pstree	//进程树
pstree -sp pid号 //查看指定进程关系
    
他是发信号的形式,不是真kill(名字)    
kill  //-9杀死进程/-18继续进程/-19暂停进程
killall -9 a.out
    
kill -2 PID  15	//发送信号+PID对应的进程,默认接收者关闭

四:fork

pid_t fork();

一次调用,会返回两次。
子进程先运行和是父进程先进程,顺序不确定。
变量不共享。
子进程复制父进程的0到3g空间和父进程内核中的PCB,但id号不同。
功能:通过该函数可以从当前进程中克隆一个同名新进程。
克隆的进程称为子进程,原有的进程称为 父进程。
子进程是父进程的完全拷贝。
子进程的执行过程是从fork函数之后执行。
子进程与父进程具有相同的代码逻辑。

返回值:int 类型的数字。
在父进程中:成功 返回值是子进程的pid号 >0
失败 返回-1;
在子进程中:成功 返回值 0
失败 无

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

//父子进程公用同一个代码段
int main(int argc, char *argv[])
{

    pid_t ret = fork();
    if(ret>0)//父
    {
        while(1)
        {
            printf("发送视频...\n");
            sleep(1);
        }
    }
    else if(0 == ret)//子
    {

        while(1)
        {
            printf("接收控制\n");
            sleep(1);
        }
    }
    else  
    {
        perror("fork error\n");
        return 1;
    }
    return 0;
}
//注意:1.父子进程创建后之后,2者都有独立的4G空间(32位)

//2.父子的数据相互独立,各自的修改只会对自己有影响
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int a = 0;
int main(int argc, char *argv[])
{

    pid_t ret = fork();
    if(ret>0)
    {
        sleep(5);//子进程会复制父进程的内存空间(包括全局变量 a 的初始值 0)。
//父子进程的 a 完全独立,修改互不影响。
        printf("father  a is %d\n",a);
    }
    else if(0 == ret)
    {
        a +=10;
        printf("child  a is %d\n",a);
    }
    else  
    {
        perror("fork error\n");
        return 1;
    }
    printf("a is %d\n",a);
    return 0;
}
fork()&&fork()||fork();有几个进程------5//3fork(4-8个)
    //有fork1父,fork2父-父,fork2父-子,fork3父-父-子,fokr3父-子-子

子进程是父进程的副本。子进程获得父进程数据段,堆,栈,正文段共享。
在fork之后,一般情况那个会先运行,是不确定的。如果非要确定那个要先运行,需要IPC机制

4.1证明父子进程同时写入数据
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

int count_Proc() {
  DIR *dp;
  struct dirent *dirp;
  int i, len, count = 0;

  if ((dp = opendir("/proc")) == NULL) {
    fprintf(stderr, "%s file %d line %s", __FILE__, __LINE__, strerror(errno));
    exit(1);
  }
  while ((dirp = readdir(dp)) != NULL) {
    if (dirp->d_type == DT_DIR) {
      len = strlen(dirp->d_name);
      for (i = 0; dirp->d_name[i] != 0; ++i) {
        if (!isdigit(dirp->d_name[i])) {
          break;
        }
      }
      if (len == i) {
        ++count;
      }
    }
  }
  closedir(dp);
  return count;
}

int main(int argc, char *argv[]) {
  FILE *fp = fopen("1.txt", "w");
  pid_t ret = fork();
  time_t tm;

  int i = 4;
  while (i--) {
    if (ret > 0) {
      time(&tm);
      struct tm *tm_info = localtime(&tm);
      int count = count_Proc();
      char buffer[10] = "hello";
      sleep(2);
      fprintf(fp, "father pid:%d\n",getpid());
      fflush(fp);//刷新缓冲区,即时写入
      fprintf(fp, "father pid:%d\n",getpid());

      printf("father fork pid:%d Proc:%d %d-%d-%d %d:%d:%d\n", getpid(), count,
             tm_info->tm_year + 1900, tm_info->tm_mon + 1, tm_info->tm_mday,
             tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec);
      

    } else if (0 == ret) {
      time(&tm);
      struct tm *tm_info = localtime(&tm);
      char buffer[10] = "world";
      int count = count_Proc();
      fprintf(fp, "child pid:%d\n",getpid());
      fflush(fp);//刷新缓冲区,即时写入
      printf("child fork pid:%d Proc:%d %d-%d-%d %d:%d:%d\n", getpid(), count,
             tm_info->tm_year + 1900, tm_info->tm_mon + 1, tm_info->tm_mday,
             tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec);
      sleep(1);
    } else {
      perror("fork error\n");
      return 1;
    }
  }
  fclose(fp);
  return 0;
}

五:getpid/getppid

pid_t getpid(void);

功能: 获得调用该函数进程的pid
返回值: 进程的pid

pid_t getppid(void);

功能: 获得调用该函数进程的父进程pid号
返回值: 返回父进程id号

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>


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

    pid_t ret = fork();
    if(ret>0)
    {
        int i =5;
        while(i--)
        {
            printf("发送视频... pid:%d ppid:%d\n",getpid(),getppid());
            sleep(1);
        }
    }
    else if(0 == ret)
    {

        int i = 5;
        while(i--)
        {
            printf("接收控制...pid:%d ppid:%d\n",getpid(),getppid());
            sleep(1);
        }
    }
    else  
    {
        perror("fork error\n");
        return 1;
    }
    printf("pid:%d ppid:%d\n",getpid(),getppid());
    return 0;
}

//打印的结果可能并不是父进程走完,子进程再走,系统就会保证在这个时间段中,
//都走过进程就可以,其中再详细的------涉及进程之间的权重计算

六:进程终止条件

//主动退出
1.main 中return
2.exit(), c库函数,会执行io库的清理工作,关闭所有 的流,以及所有打开的文件。已经清理函数(atexit)。
3._exit,_Exit 会关闭所有的已经打开的文件,不执行清理函数。
4.	主线程退出
5.主线程调用pthread_exit异常终止
6.abort()
7.signal   kill pid
8.最后一个线程被pthread_cancle

七:exit

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

    printf("hello");
    exit(EXIT_SUCCESS);//标准退出
    _exit(EXIT_SUCCESS);// 直接退出,立即终止进程,跳过清理	//可能会导致资源没有被释放
    printf("-----------\n");
    return 0;
}

前两天做项目,做那个EDID的项目,说实在的,他但凡英语文档有中文版,也不至于写2天,还有英文文档还是不全的,还要上网搜,做的有力使不出,总结做这个:基础还要进一步巩固,位运算的理解进一步加深,


网站公告

今日签到

点亮在社区的每一天
去签到