当前位置:网站首页>图图的学习笔记-进程

图图的学习笔记-进程

2022-07-06 09:28:00 Larry_Yanan

进程

创建进程
fork与vfork说明:
fork和vfork都是用来创建子进程
vfork—父进程要等子进程退出后在运行, (写时复制)
fork创建子进程,父子进程谁先执行由系统调度决定
进程资源回收—由父进程回收资源
僵尸进程:子进程退出,父进程没有帮其回收资源,这个时候子进程就是僵尸进程 (一定要要避免产生)
孤儿进程:子进程还在运行,父进程退出,那么这时候的子进程就是孤儿进程


进程退出(exit(1))
进程退出方式:
1.进程运行完退出
2.通过exit()退出 进程–关闭文件描述符, 清空缓冲区
3._exit()退出 只是关闭进程,不会处理文件描述符,缓冲区exec函数族运行过程


在父进程中用fork创建子进程,在子进程中用exec函数族来执行新的程序,
exec函数会用新的程序数据段, 代码段覆盖子进程的数据和代码, 从新程序的入口开始执行(堆和栈是原型子进程里面的,在exec函数前面尽量不要使用堆空间和栈空间)
例子是ls之类的…


进程间通信IPC
管道
map映射空间共享
信号
消息队列
共享内存
信号量
套接字

————————————————————————
管道通信
管道文件-----FIFO ,

1.无名管道 : pipe —没有实际的文件,只是在内核区分配一段内存空间模拟管道
pipe创建无名管道会得到两个文件描述符(一个用来读, 一个用来写)
int pipe(int pipefd[2]);
//创建管道文件
int fds[2];
int ret = pipe(fds);//fds[0]–读文件描述符, fds[1]-写文件描述符

读取管道文件的时候如果管道中没有数据,read会阻塞
无名管道通信只适用于父子进程

  1. 有名管道—实现非亲属进程间通信
    1). 必须要有个管道文件
    mkfifo函数创建管道文件 fio
    2). 在A进程中打开管道文件fio
    在B进程中打开管道文件fio
    3).在A进程中往管道写数据
    在B进程中从管道中读取数据
//A
//1打开管道文件
int fd = open("/home/gec/fio", O_RDWR);

//2往管道中写数据
write(fd, "hello world linux", 18);

//3关闭管道文件
close(fd);

//B
//1打开管道文件
int fd = open("/home/gec/fio", O_RDWR);

//2从管道中读取数据
char buffer[32];
read(fd, buffer, 32);
printf("%s\n", buffer);

//3关闭管道文件
close(fd);

mmap映射内存实现进程间通信
父子进程共享一片内存,可以同时操作
#include <sys/mman.h>
void *mmap(void addr, size_t length, int prot, int flags, int fd, off_t offset); //映射
参数:void addr指定的用户空间(设置为NULL, 系统自动分配)
size_t length映射空间大小
int prot 权限----如果是文件必须与文件权限对象
int flags—设置空间私有MAP_PRIVATE,共享MAP_SHARED等权限
MAP_SHARED|MAP_ANONYMOUS–匿名映射(fd要设置为-1, offset也是0)
int fd --要映射的文件
off_t offset --映射对应设备的偏移量
返回值:void
映射到用户空间的首地址 (如果失败 (void
)-1)
int munmap(void *addr, size_t length);//释放映射

用mmap匿名映射实现父子进程间通信


  1. linux下发生信号
    命令:kill 信号 进程id号
    函数:
    #include <sys/types.h>
    #include <signal.h>
    int kill(pid_t pid, int sig); //参数:进程id号, 信号
  2. 捕获信号(拦截信号)
    #include <signal.h>
    typedef void (*sighandler_t)(int); //定义一个函数指针类型sighandler_t
    sighandler_t signal(int signum, sighandler_t handler);
    handler指向另一个函数

kill发送信号—对任意进程
------》
对本进程发送信号
raise abort alarm setitimer
1)raise
int raise(int sig); ===》kill(getpid(), sig);
raise(SIGUSR1);
直接给本进程传信号
SIGUSE1:用户定义 的信号。即程序员可以在程序中定义并使用该信号。默认动作为终止进程。

2)abort
abort() — 给当前进程发送SIGABRT信号,并且终止进程,把文件关闭清空缓冲区,把进程信息存储在核心文件core中

3)alarm
alarm —闹铃 定时给本进程发送SIGALRM信号
unsigned int alarm(unsigned int seconds);
参数:seconds 设置定时时间
如果当前进程在sleep中,接到alarm发送的SIGALRM信号会被唤醒

4)setitimer
setitimer—给本进程发送SIGALRM信号 --计时 发送
//拦截信号
signal(SIGALRM, handle);
//发送信号
struct itimerval newit, oldit;
//初始化newit
newit.it_interval.tv_sec = 1;
newit.it_interval.tv_usec = 0;
newit.it_value.tv_sec = 1;
newit.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &newit, &oldit);

总结:信号可以被拦截,程序中可以通过多种方式进行发送信号,还可以定时


重复一下:
进程间通信IPC
管道
map映射空间共享
信号
消息队列
共享内存
信号量
套接字


消息队列
1.获取键值
2.根据键值获取消息队列int msgget(key_t key, int msgflg);
3.往队列里面发送/接受数据
msgsnd(msgid, &msgbuffer, sizeof(msgbuffer), 0);
这个buffer要另外设,包含大小和一个数组
肤浅的认为是创建了一个“消息队列”吧,然后像管道一样传输数据


共享内存
1.获取键值
2.根据键值获取共享内存int shmget(key_t key, size_t size, int shmflg);
3.映射空间(内核共享内存映射用户空间)
4.释放映射shmdt(mp);
5.释放共享内存shmctl(shmid, IPC_RMID, NULL);
在内核创建一片“共享内存”,映射到用户空间后就可以操作使用了;通过键值去多进程通信吧


信号量
用信号量实现两个进程同步与互斥
暂时没有发现通讯…


守护进程(精灵进程),后台服务程序,成员名以d结尾
守护进程与控制台分离,在后台运行(一般用于后台服务程序)—孤儿进程


系统日志

原网站

版权声明
本文为[Larry_Yanan]所创,转载请带上原文链接,感谢
https://blog.csdn.net/Larry_Yanan/article/details/108330853