进程编程,进程间通信

一、进程的概念

1.什么是程序:

存放在磁盘上的指令和数据的有序集合(文件)是静态的

2.什么是进程 :

进程是程序的一次执行过程,是动态的包括创建,调度,执行和消亡

3.进程内容:

在这里插入图片描述
系统数据包括:进程控制块(进程PID进程号,进程用户,状态,优先级,文件描述符表)CPU寄存器(进程调度,实现宏观上的并发),堆栈

4.进程类型:

交互进程
批处理进程
守护进程

5.进程状态

运行态
等待态
可中断
不可中断
停止态
死亡态
在这里插入图片描述

二、查看进程信息

1.ps 查看系统进程快照
2.top 查看进程动态信息
3. ./proc 文件查看

三 、进程相关命令

1.nice 按用户优先级运行进程

3.renice 改变正在运行的进程优先级
4.jobs 查看后台进程
5.bg 将挂起的进程在后台运行
6.fg 把后台运行的进程放到前台运行

四、进程相关命令

1.进程的创建-----fork()

创建信的进程,失败是返回-1;
成功是父进程返回进程的进程号,子进程返回0;
通过返回值区分父子进程;


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

int main ()
{
   
    pid_t pid;
    if((pid = fork()) < 0){
   
        perror("fork");
        exit(-1);
    }else if(pid == 0){
   
        printf("child process: my pid = %d\n",getpid());  
    }else{
   
        printf("parent process: my pid = %d\n",getpid());  
    }
    return 0;
}

2.父子进程的关系

子进程继承了父进程的内容
父子进程有独立的地址空间,互不影响
若父进程先结束: 子进程成为孤儿进程,被init进程收养 ,子进程变成后台进程
若子进程先结束:父进程没有及时回收子进程变成僵尸态进程.
子进程从何时开始运行?
从fork下一条语句开始运行
父子进程谁先执行?
内核调度,都有可能先运行.

3.进程结束 exit/_exit

void exit(int status);
void _exit(int staus);
结束当前进程并将status返回
exit结束进程时回刷新缓冲区

int main ()
{
   
    printf("hello");
    exit(0);
    printf("word");
}

运行结果:hello

int main ()
{
   
    printf("hello");
    _exit(0);
    printf("word");
}

运行结果:没有任何显示.

4.exec 函数族

进程调用exec 函数族执行某个程序
进程当前的内容被指定程序替换
实现让父子进程执行不同的程序:
1.父进程创建子进程
2.子进程调用exec函数族
3.父进程不受影响
(shell终端)

① execl/execlp

int execl(const char *path,const char *arg,…);
const *path : 执行的程序名称,包含路径;
const char arg :传递给执行程序的参数列表,最后一个传NULL
成功返回指定程序;失败返回EOF
int execlp(const char
file,const char *arg,…);
const *file : 执行的程序名称,不包含路径;
在PATH中查找
const char *arg :传递给执行程序的参数列表,最后一个传NULL
成功返回指定程序;失败返回EOF

② execv/execvp

int execv(const char *path,char *const argv[],…);
对比:execl 只是把执行程序的参数换成字符指针数组
int execvp(const char *file,char *const argv[],…);
对比:execlp只是把执行程序的参数换成字符指针数组
比上面的更灵活

③system

int system (const char *command);

成功返回命令commamd 的返回值;失败返回EOF
自动创建子进程.
当前的进程等待commamd 进程结束才继续运行.

5.进程回收

①pid_t wait(int *status);

pid_t wait(int *status);
成功返回子进程进程号,失败返回EOF
若子进程没有结束,父进程一直阻塞
若多个子进程,哪个先结束就先回收.
status 指定保存子进程返回值的结束方式
status为NULL标识直接释放子进程PCB,不接收返回值
子进程通过exit/_exit/return 返回某个值(0-255);
父进程调用wait(&status)回收
WIFEXITED(status) 判断进程是否正常结束
WEXITSTATUS(status) 获取子进程返回值
WIFSIGNALED(status) 判断子进程是否被信号结束
WTERMSIG(status); 获取结束子进程的信号类型

② pid_t waitpid(pid_t pid ,int *status,int option);

pid_t waitpid(pid_t pid ,int *status,int option);
成功返回回收的子进程的pid或者0(子进程还没结束),失败返回EOF
pid 可用于指定回收哪个子进程或者任意子进程(传-1);
status指定用于保存子进程返回值和结束方式的地址
option 指定回收方式 0(阻塞方式) 或者WNOHANG(非阻塞)

五、守护进程

通常在系统启动是运行,系统关闭时结束
守护进程特点:始终在后台运行,独立于任何终端(避免终端关闭的时候守护进程退出),周期性的执行某种任务或者等待处理特定的事件.

1.守护进程的创建

1.创建子进程,父进程退出

if(fork()>0){
   
	exit(0);
}

子进程变成孤儿进程,被init 进程收养
子进程在后台运行
2.子进程创建新会话

if(setsid()<0){
   
	exit(-1);
}

子进程成为新的会话组组长
子进程脱离原先的终端
3.更改当前进程的工作目录

chdir("/");
chdir("/tmp");

守护进程一直在后台运行,其工作目录不能被卸载
4.重设文件权限掩码

if(umask(0)<0){
   
	exit(-1);
}

5.关闭打开的文件描述符


int i;
for(i=0;i<gettablesize();i++){
   
	close(i);
}

关闭所有从父进程继承的打开文件
已经脱离终端, stdin/stout/stderr无法再使用

创建守护进程,每隔一秒向time.log里写人系统时间

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

int main()
{
   
    pid_t pid;
    FILE *fp;
    time_t t;
    int i;
    if((pid = fork())<0){
   
        perror("fork");
        exit(-1);
    }else if(pid>0){
   
        exit(0);
    }
    setsid();
    umask(0);
    chdir("/tmp");
    for(i=0;i<getdtablesize();i++){
   
        close(i);
    }
    if((fp = fopen("time.log","a")) == NULL){
   
        perror("fopen");
        exit(-1);
    }
    while(1){
   
        time(&t);  
        fprintf(fp,"%s",ctime(&t));
        fflush(fp);
        sleep(1);
    }
    return 0;

}

在这里插入图片描述

六、进程间通信

1.无名管道(pipe)

在这里插入图片描述
无名管道的特点:
只能用于具有亲缘关系 的进程之间的通信(无名管道文件系统不可见,非亲缘关系的不认识此文件描述符)
单工(不能同时写和读)的通信模式,具有固定的读端和写端
无名管道创建是会返回两个文件描述符,分别用于读写管道

无名管道的创建:

int pipe(int pfd[2]);

成功返回0,失败返回-1;
pfd:包含两个元素的整形数组,用于保存文件描述符
pfd[0] 读管道 pfd[1] 写管道
实现子进程一和子进程二分别写消息,父进程读


#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main ()
{
   
    char buf[32];
    pid_t pid1,pid2;
    int pfd[2];

    if(pipe(pfd) <0){
   
        perror("pipe");
        exit(-1);
    }
    if((pid1 = fork())<0){
   
        perror("fork:");
        exit(-1)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值