共享内存、守护进程

一、共享内存

1.定义

2.使用步骤

3.相关函数

#include <sys/ipc.h>

#include <sys/shm.h>

1.int shmget(key_t key, size_t size, int shmflg);

    - 功能:创建一个新的共享内存段,或者取一个既有的共享内存段的标识。

        新创建的内存段中的数据都会被初始化为0

    - 参数:

        - key : key_t类型是一个整形,通过这个找到或者创建一个共享内存。

                一般使用16进制表示,非0值,可随意设置

        - size: 共享内存的大小

        - shmflg: 属性

            - 访问权限

            - 附加属性:创建 / 判断共享内存是不是存在

                - 创建:IPC_CREAT

                - 判断共享内存是否存在: IPC_EXCL , 需要和IPC_CREAT一起使用

                    IPC_CREAT | IPC_EXCL | 0664

        - 返回值:

            失败:-1 并设置错误号

            成功:>0 返回共享内存的引用的ID,后面操作共享内存都是通过这个值。

2.void *shmat(int shmid, const void *shmaddr, int shmflg);

    - 功能:和当前的进程进行关联

    - 参数:

        - shmid : 共享内存的标识(ID),由shmget返回值获取

        - shmaddr: 申请的共享内存的起始地址指定NULL,内核指定

        - shmflg : 对共享内存的操作

            - 读 : SHM_RDONLY, 必须要有读权限

            - 读写: 0

    - 返回值:

        成功:返回共享内存的首(起始)地址。  失败(void *) -1

3.int shmdt(const void *shmaddr);

    - 功能:解除当前进程和共享内存的关联

    - 参数:

        shmaddr:共享内存的首地址

    - 返回值:成功 0, 失败 -1

4.int shmctl(int shmid, int cmd, struct shmid_ds *buf);

    - 功能:对共享内存进行操作。

        只有删除共享内存,共享内存才会消失,创建共享内存的进程被销毁了对共享内存是没有任何影响。

    - 参数:

        - shmid: 共享内存的ID

        - cmd : 要做的操作

            - IPC_STAT : 获取共享内存的当前的状态

            - IPC_SET : 设置共享内存的状态

            - IPC_RMID: 标记共享内存被销毁

        - buf:需要设置或者获取的共享内存的属性信息

            - IPC_STAT : buf用来存储数据

            - IPC_SET : buf中需要初始化数据,设置到内核中

            - IPC_RMID : 没有用,NULL

5.key_t ftok(const char *pathname, int proj_id);

    - 功能:根据指定的路径名,和int值,生成一个共享内存的key

    - 参数:

        - pathname:指定一个存在的路径

            /home/nowcoder/Linux/a.txt            

        - proj_id: int类型的值,但是这系统调用只会使用其中的1个字节

                   范围 : 0-255  一般指定一个字符 'a'

4.相关命令 ipcs  ipcrm

 5.重要问题

问题1:操作系统如何知道一块共享内存被多少个进程关联?

    - 共享内存维护了一个结构体struct shmid_ds 这个结构体中有一个成员 shm_nattch

    - shm_nattach 记录了关联的进程个数

问题2:可不可以对共享内存进行多次删除 shmctl

    - 可以的

    - 因为shmctl 是标记删除共享内存,不是直接删除

    - 什么时候真正删除呢?

        当和共享内存关联的进程数为0的时候,就真正被删除

    - 共享内存被标记删除后,共享内存的key为0

        如果一个进程和共享内存取消关联,那么这个进程就不能继续操作这个共享内存,也不能进行关联。

问题3:共享内存和内存映射的区别

    1.共享内存可以直接创建内存映射需要磁盘文件(匿名映射除外

    2.共享内存效果更高

    3.内存

        共享内存:所有的进程操作的是同一块共享内存

        内存映射:每个进程在自己的虚拟地址空间中有一个独立的内存。

    4.数据安全

        - 进程突然退出

            共享内存还存在

            内存映射区消失

        - 运行进程的电脑死机,宕机了

            数据存在在共享内存中,没有了

            内存映射区的数据 ,由于磁盘文件中的数据还在,所以内存映射区的数据还存在。

    5.生命周期

        - 内存映射区:进程退出,内存映射区销毁

        - 共享内存:进程退出,共享内存还在。标记删除(且关联的进程数为0),或者关机,共享内存块消失

            如果一个进程退出,会自动和共享内存进行取消关联。

二、守护进程 

查看当前终端的进程号:echo $$ 

查看当前终端:tty

~:表示当前登录的用户的用户目录 /home/chen

1.终端

2.进程组

3.会话

4.关系

5.函数

6.守护进程

7.守护进程创建步骤

 示例:

/*
    写一个守护进程,每隔2s获取一下系统时间,将这个时间写入到磁盘文件中。
*/

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <signal.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>

void work(int num){
    // 捕捉到信号之后,获取系统时间,写入磁盘文件
    time_t t = time(NULL);              //秒
    struct tm * loc = localtime(&t);     //将time_t类型数据转化成对应时间
    char * str = asctime(loc);

    int fd = open("time.txt",O_RDWR|O_CREAT|O_APPEND,0664);
    write(fd,str,strlen(str));
    close(fd);
}

int main(){

    //1.创建子进程
    pid_t pid = fork();
    if(pid > 0){
        //父进程退出
        exit(0);
    }

    //2.子进程重新创建一个会话
    //新的会话没有控制终端,无法通过终端给会话发送消息
    //子进程创建会话,首先创建一个进程组,进程组组号是子进程号,不会和别的进程组产生冲突
    setsid();

    //3.设置掩码
    umask(022);

    //4.更改工作目录
    chdir("/home/chen");

    //5.关闭、重定向文件描述符
    //关闭所有从父进程继承来的打开的文件描述符
    //打开/dev/null,将标准输入、输出、错误重定向到此;/dev/null会自动忽略输入输出
    int fd = open("/dev/null",O_RDWR);
    dup2(fd,STDIN_FILENO);
    dup2(fd,STDOUT_FILENO);
    dup2(fd,STDERR_FILENO);

    //6.主要业务逻辑
    
    //注册信号捕捉
    struct sigaction act;
    act.sa_flags = 0;
    act.sa_handler = work;
    sigemptyset(&act.sa_mask);

    sigaction(SIGALRM,&act,NULL);

    //创建定时器
    struct itimerval val;
    //延迟3秒,每隔2秒定时一次
    val.it_value.tv_sec = 3;
    val.it_value.tv_usec = 0;
    val.it_interval.tv_sec = 2;
    val.it_interval.tv_usec = 0;

    setitimer(ITIMER_REAL,&val,NULL);

    //阻止进程结束
    while(1){
        
    }

    return 0;
}

2023.7.24

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值