美文网首页
操作系统

操作系统

作者: bangbang2 | 来源:发表于2022-01-23 19:38 被阅读0次

    进程的五种状态

    1:new 进程正在被创建,尚未达到ready状态

    2:ready状态,进程已经获得除了cpu的一切其他资源----万事具备,只欠东风

    3:running状态

    4:waiting状态---正在等待获得其他资源--io资源等

    5:结束状态

    image.png

    进程与线程的区别

    进程是资源分配的基本单位,线程是任务执行的基本单位
    线程的程序计算器、本地方法区、虚拟机栈是独立的,堆和方法区是共享的

    image.png

    进程通信

    匿名管道

    一般是父子进程或兄弟进程之间的通信,半双工模式,有固定的读端(fd[0])和写端(fd[1])


    image.png
    image.png
    #include<stdio.h>
    #include<unistd.h>
    
    int main()
    {
        int fd[2];  // 两个文件描述符
        pid_t pid;
        char buff[20];
    
        if(pipe(fd) < 0)  // 创建管道
            printf("Create Pipe Error!\n");
    
        if((pid = fork()) < 0)  // 创建子进程
            printf("Fork Error!\n");
        else if(pid > 0)  // 父进程
        {
            close(fd[0]); // 关闭读端
            write(fd[1], "hello world\n", 12);
        }
        else
        {
            close(fd[1]); // 关闭写端
            read(fd[0], buff, 20);
            printf("%s", buff);
        }
    
        return 0;
    }
    
    命名管道

    不具有亲缘关系的进程也可以使用

    消息队列

    消息的链接表,独立于发送和接收线程,有特定的优先级,可以随机进行访问

    #include <sys/msg.h>
    // 创建或打开消息队列:成功返回队列ID,失败返回-1
    int msgget(key_t key, int flag);
    // 添加消息:成功返回0,失败返回-1
    int msgsnd(int msqid, const void *ptr, size_t size, int flag);
    // 读取消息:成功返回消息数据的长度,失败返回-1
    int msgrcv(int msqid, void *ptr, size_t size, long type,int flag);
    // 控制消息队列:成功返回0,失败返回-1
    int msgctl(int msqid, int cmd, struct msqid_ds *buf);
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/msg.h>
    
    // 用于创建一个唯一的key
    #define MSG_FILE "/etc/passwd"
    
    // 消息结构
    struct msg_form {
        long mtype;
        char mtext[256];
    };
    
    int main()
    {
        int msqid;
        key_t key;
        struct msg_form msg;
    
        // 获取key值
        if((key = ftok(MSG_FILE,'z')) < 0)
        {
            perror("ftok error");
            exit(1);
        }
    
        // 打印key值
        printf("Message Queue - Server key is: %d.\n", key);
    
        // 创建消息队列
        if ((msqid = msgget(key, IPC_CREAT|0777)) == -1)
        {
            perror("msgget error");
            exit(1);
        }
    
        // 打印消息队列ID及进程ID
        printf("My msqid is: %d.\n", msqid);
        printf("My pid is: %d.\n", getpid());
    
        // 循环读取消息
        for(;;)
        {
            msgrcv(msqid, &msg, 256, 888, 0);// 返回类型为888的第一个消息
            printf("Server: receive msg.mtext is: %s.\n", msg.mtext);
            printf("Server: receive msg.mtype is: %d.\n", msg.mtype);
    
            msg.mtype = 999; // 客户端接收的消息类型
            sprintf(msg.mtext, "hello, I'm server %d", getpid());
            msgsnd(msqid, &msg, sizeof(msg.mtext), 0);
        }
        return 0;
    }
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/msg.h>
    
    // 用于创建一个唯一的key
    #define MSG_FILE "/etc/passwd"
    
    // 消息结构
    struct msg_form {
        long mtype;
        char mtext[256];
    };
    
    int main()
    {
        int msqid;
        key_t key;
        struct msg_form msg;
    
        // 获取key值
        if ((key = ftok(MSG_FILE, 'z')) < 0)
        {
            perror("ftok error");
            exit(1);
        }
    
        // 打印key值
        printf("Message Queue - Client key is: %d.\n", key);
    
        // 打开消息队列
        if ((msqid = msgget(key, IPC_CREAT|0777)) == -1)
        {
            perror("msgget error");
            exit(1);
        }
    
        // 打印消息队列ID及进程ID
        printf("My msqid is: %d.\n", msqid);
        printf("My pid is: %d.\n", getpid());
    
        // 添加消息,类型为888
        msg.mtype = 888;
        sprintf(msg.mtext, "hello, I'm client %d", getpid());
        msgsnd(msqid, &msg, sizeof(msg.mtext), 0);
    
        // 读取类型为777的消息
        msgrcv(msqid, &msg, 256, 999, 0);
        printf("Client: receive msg.mtext is: %s.\n", msg.mtext);
        printf("Client: receive msg.mtype is: %d.\n", msg.mtype);
        return 0;
    }
    
    信号量

    信号量是利用PV原语来实现进程同步

    共享内存

    效率最高,多个进程去对某一个内存进行访问

    信号

    信号:作为一种软中断,一个进程可以发出信号给操作系统,操作系统然后去通知另一个进程,然后该进程中断一下去执行
    kill()函数主要用于向指定的进程或进程组发送信号

    image.png

    线程同步

    线程同步:多个线程在竞争过程中,能保证保证代码顺序执行


    image.png

    1:互斥锁
    pthread_mutex_lock就是上锁的函数,pthread_mutex_unlock就是解锁的函数

    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    int gTotalTickerNum = 20;
    
    void *sellTicket(void *arg) {
      for (int i = 0; i < 20; i++) {
        pthread_mutex_lock(&mutex);
        if (gTotalTickerNum > 0) {
          sleep(1);
          printf("sell the %dth ticket\n", 20 - gTotalTickerNum + 1);
          gTotalTickerNum--;
        }
        pthread_mutex_unlock(&mutex);
      }
      return nullptr;
    }
    

    在多线程同步中的用到的比较多

    image.png

    Mutex相当于一把钥匙

    image.png

    2:条件变量
    和互斥锁一起用
    3:读写锁
    写锁独占,读锁共享
    4:信号量
    信号量类似一个容纳n个人的房间,限制同时访问的量

    image.png

    管程

    为什么引入monitor?
    信号量保证不了执行的顺序,也可能导致错误
    将共享变量和操作原语封装在一个对象中,保证去顺序执行这些操作


    image.png

    相关文章

      网友评论

          本文标题:操作系统

          本文链接:https://www.haomeiwen.com/subject/wupmhrtx.html