Linux进程基础

Linux进程基础

进程指正在运行的程序,是资源分配的最小单位,可以通过“ ps " 或 "top"等命令查看正在运行的程序。线程是系统的最小调度单位,一个进程可以拥有多个线程,同一进程里的线程可以共享此进程的同一资源。

每个进程都有一个唯一的标识符,基进程ID,简称pid

进程间的通信的几种方法:

  1. 管道通信:有名管道 无名管道

  2. 信号通信: 信号的发送 信号的接受 信号的处理

  3. IPC通信: 共享内存 消息队列 信号灯

  4. Socket 通信

    进程的三种基本状态以及转换:

1.创建进程

所有的进程都是由其他进程创建(除了pid为0号的idle进程),pid号为1的init进程是系统启动后运行的第一个进程,是所有进程的父进程,init进程会初始化一部分系统服务,创建其他进程。

创建新进程的那个进程成为父进程,新进程称为子进程,父进程和子进程拥有相同的代码段数据段,有各自独立的地址空间。采用写时拷贝技术。

创建进程常用函数定义如下:

     #include <stdio.h>
     #include <unistd.h>
     
     int main(void)
     {
         pid_t pid;
         pid = fork();
         if(pid < 0)
         {
             printf("fork is error\n");
             return -1;
         }
         if(pid > 0)
         {
             printf("This is parent process,parent pid is %d\n", getpid());
     
         }
         if(pid == 0)
         {
             printf("This is clild process,child pid is %d,parent pid is %d\n", getpid(), getppid());
         }
     
         return 0;
         
     }

2.exec函数族

用fork函数创建子进程后,子进程往往要调用一种exec函数以执行另一个程序,该子进程被新的程序替换,改变地址空间,进程映像和一些属性,但pid号不变。

以下函数都是根据 execve 实现:

int execl(const char *path, const char *arg, .../* (char *) NULL */);
int execlp(const char *file, const char *arg, .../* (char *) NULL */);
int execle(const char *path, const char *arg, .../*, (char *) NULL, char * const envp[] */);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);

3.ps和kill命令

ps 命令:ps命令可以列出系统中当前运行的那些进程

命令格式: ps[参数]

命令功能:用来显示当前进程的状态

常用参数: aux

kill 命令:kill命令用来杀死进程

举例: kill -9(SIGKILL) PID

进程的状态

D: 无法中断的休眠状态 (通常 IO 的进程)
R: 正在执行中
S: 静止状态
T: 暂停执行
Z: 不存在但暂时无法消除
W: 没有足够的记忆体分页可分配
<: 高优先序的行程
N: 低优先序的行程
L: 有记忆体分页分配并锁在记忆体内 (实时系统或捱 A I/O)

4.孤儿进程和僵尸进程

孤儿进程: 父进程结束以后,子进程还未结束,这个子进程就叫做孤儿进程。

僵尸进程:子进程结束以后,父进程还在运行,但是父进程不去释放进程控制块,这个进程就叫做僵尸进程。

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

int main()
{
	int i = 0;
	pid_t pid;
	pid = fork();
	if(pid < 0)
	{
		printf("fork is error \n");
		return -1;
	}
	if(pid > 0)
	{
		printf("pid is %d\n", getpid());
	}
	if(pid == 0)
	{
		sleep(2);
		printf("parent pid is %d\n", getppid());
	}
	return 0;
}

如上图所示,子进程中打印的父进程的进程号和父进程的进程号是不一样的,说明创建的子进程变成了孤儿进程,此进程被系统的int 进程 “领养”了。

lmg        1479  0.0  0.0  48392  4964 ?        Ss   1月11   0:00 /sbin/upstart --user
lmg       10431  0.0  0.0  15984  1012 pts/20   S+   17:08   0:00 grep --color=auto 1479
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
int i=0;
pid_t pid;
// 创建一个子进程
pid = fork();
 	if (pid < 0)
	{
		printf("fork is error \n");
		return -1;
	}
	if (pid > 0)
	{
		while(1);
	} //子进程,让子进程先结束
	if (pid == 0)
	{
		printf("This is child\n");
		exit(0);
	} 
    return 0;
}

5. 守护进程

守护进程(daemon)是一类在后台运行的特殊进程, 用于执行特定的系统任务。 很多守护进程在系统引导的时候启动, 并且一直运行直到系统关闭。 另一些只在需要的时候才启动, 完成任务后就自动结束。

创建守护进程

1.使用 fork 函数创建一个新的进程, 然后让父进程使用 exit 函数直接退出(必须要的)
2.调用 setsid 函数。 (必须要的)
3.调用 chdir 函数, 将当前的工作目录改成根目录, 增强程序的健壮性。 (不是必须要的)
4.重设我们 umask 文件掩码, 增强程序的健壮性和灵活性(不是必须要的)
5.关闭文件描述符, 节省资源(不是必须要的)
6.执行我们需要执行的代码(必须要的)

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(void)
{
pid_t pid;
// 步骤一: 创建一个新的进程
pid = fork();
//父进程直接退出
if (pid > 0)
{
	exit(0);
}
if (pid == 0)
{
  // 步骤二: 调用 setsid 函数摆脱控制终端
  setsid();
// 步骤三: 更改工作目录
  chdir("/");
// 步骤四: 重新设置 umask 文件源码
  umask(0);
// 步骤五: 0 1 2 三个文件描述符
   close(1);
   close(2);
   close(3);
// 步骤六: 执行我们要执行的代码
while (1)
  { 
  }
}
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值