Linux高级编程:进程(一)

1、进程

1.1什么是进程:进行中的程序(正在运行中的程序)-process过程

        程序的一次执行过程 - 进程

        hello.c --  程序源代码

        a.out   --  可执行程序

1.2程序和进程的关系:

        程序<------>进程

1.3进程怎么来的:

        程序->加载到内存(运行起来了)-->进程

1.4总结:

进程 ---动态---内存

程序---静态----硬盘

1个程序可以对应一个或多个进程

1.5为什么需要进程

时间片轮转

若要保存上次程序运行到哪了,则需记录-程序的执行状态

则需要进程这个概念了

描述和记录,正在运行中的程序的相关信息。

进程的调度(操作系统,上下文的切换)(让它看起来程序在并发运行,其实每个程序只能运行一小会,且(单核)cpu每次只执行一个程序)

进程的执行特点:微观串行,宏观并行。

最核心的目的:提高效率。

1.6进程的组成:

1、

程序 = 代码 + 数据

bss --- 未初始化的数据 |

data --- 初始化了的数据 | 静态区 | ---数据

text --- 正文段(代码段)

bss -- 未初始化                                                                栈

----                                                                                    堆

data -- 已初始化      --------------./a.out------------>              bss

----                                                                                    data                                           

text -- 代码段                                                                   text

//linux系统下,程序的内存布局                                        //进程的实体

静态区

字符串常量区

代码段  //c语言标准的内存布局

进程 -----

pcb---是一个结构体    Process Control Block

进程 = pcb块 + 各个段(栈 | 堆 | bss | data | text)

1.7进程的生命周期:

通用三态模型:

linux系统下的状态模型:

1.8观察进程的命令:

1、top命令  :观察进程  //类似任务管理器

2、ps

man ps /state

进程状态代码:

D    uninterruptible sleep (usually IO)
R    running or runnable   (on run queue) ---就绪队列中
S    interruptible sleep   (waiting for an event to complete)
T    stopped(暂停态), 
                    either by a job control signal or because it is being traced.
*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.

查看进程相关信息

1.就绪态、运行态 R

2.睡眠态、等待态

        可唤醒等待态 S

        不可唤醒等待态 D

3.停止态 T

4.僵尸态 Z

5.结束态

ps aux | grep 进程名 (pid号)  //当前进程的id号 及 状态

此命令可以察看所有同名文件

ps -eLf | grep 进程名 (pid号)   //可查看父进程id号

ppid(parent  process id)//父进程id

3、pstree

pstree -sp id号 //是两个命令合起来 {pid号(如果不写表示查看全部的)}

查看进程关系

init(1) (1号进程最早出现的一个进程)---- gnome-terminal(xxxx)----bash(xxxx)

4、kill

kill PID

kill 信号编号(-数字) 进程ID

发送信号+PID对应的进程,默认接收者关闭

kill -9 进程PID号 //杀死程序

kill -l //查看信号列表

killall 信号编号 程序名字

5、 fork()

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

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

代码示例:
int main()
{
    pid_t pid = fork();
    if(pid < 0)
    {
    	perror("fork fail");
        return -1;
    }
    if(pid >0 )
    {
        printf("father---\n");
    }
    else if (pid == 0 )
    {
        printf("child---\n");
    }
}

输出:

代码解释:

 父子进程独立操作。

练习:
1、父子进程都死循环。

        a.结束父进程,查看当前系统中父子进程的状态

        b.结束子进程,查看当前系统中父子进程的状态

#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;
      }
      if(pid >0 )
      {
          while(1)
          {
              printf("father---\n");
         }                                                                                    
      }
      else if (pid == 0 )
      {
          while(1)
         {
             printf("child---\n");
         }
      }
  
      return 0;
  }                                                                  

 a.结束父进程    //子进程成为后台进程,孤儿进程 --- 子进程还在,父进程不在。(init收养子进程。以前的版本)

b.结束子进程   //子进程结束,父进程还在 父进程没有去收尸 ---子进程呈僵尸态,若此时结束父进程,则子进程的实尸体被系统收养,但系统发现子进程已死则直接销毁回收,不然僵尸态(户口信息)会占用内存。

 2、

自己分别定义一个 static的变量 static int a = 0; 全局变量 int b = 1; 堆区 int *p = (int *)malloc(sizeof(int)); *p = 2; (做修改)父进程中 做加1的操作 ,子进程中做加2的操作 分别打印,查看效果! 同时可以查看一下父子进程的关系(pstree) 父子进程的状态!

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

int b = 1;

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

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

	//父进程独立代码
	while(1)
	{
		if(pid > 0)
		{
			printf("father a = %d\n",a++);
			printf("father b = %d\n",b++);
			printf("father p = %d\n",(*p)++);
		}
		//子进程独立代码
		else if(pid == 0)
		{
			printf("child a = %d\n",a++);
			printf("child b = %d\n",b++);
			printf("child p = %d\n",(*p)++);
		}
		sleep(1);
	}
	return 0;
}

   父子进程之间不会影响,谁先运行的顺序由操作系统决定,尽可能公平、高效

 

3、面试题:

一次fork生成几个进程? 

他们之间的关系是什么样的? //生成1个一共有两个

如果两次fork同时前后执行,会生成几个进程? //共有(4)个进程

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

有多少个子进程,

有没有孙进程?有

4、fork()&&fork()|| fork() 总共有几个进程?

有5个进程

5、

fork();

fork();

fork();  一共有几个进程?  //  2^n个进程

 6、动态生成子进程,并打印输出各自进程的pid号
#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;
      }
      if(pid >0 )
      {
          while(1)
          {
              printf("father---%d\n",getpid());
         }                                                                                    
      }
      else if (pid == 0 )
      {
          while(1)
         {
             printf("child---%d\n",getpid());
         }
      }
  
      return 0;
  }                                                                  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值