美文网首页
进程/线程

进程/线程

作者: BlueFishMan | 来源:发表于2020-06-21 14:36 被阅读0次

    程序->进程

    编译与链接的过程图
    • (无线程)进程是最小的运行单位
    • (有线程)线程是最小的运行单位,进程是线程的容器

    Linux为每个进程维护了一个单独的虚拟地址空间

    一个Linux进程的虚拟内存

    代码段(程序可以被多个进程共享)

    进程标志符与进程、程序之间的关系

    内核为系统中的每个进程维护一个单独的任务结构(task_struct)

    • PID(pid_t,无符号整数)

    用户模式和内核模式/上下文切换

    进程上下文切换的剖析

    Linux系统启动过程

    • 0号内核进程->1号内核进程->init(execve(/etc/inittab-init程序))->1号用户进程(init进程)

    进程的创建与结束

    复制数据段/堆栈段,共享代码段

    1. 对于父进程,fork()函数返回新创建的子进程的ID
    2. 对于子进程,fork()函数返回0
    3. 如果创建出错,则如此fork()函数返回-1

    1. 正常退出,return,执行完后把控制权交给调用函数
    2. 正常退出,exit(),执行完后把控制权交给系统
    3. 异常退出,abort()

    孤儿进程是父进程已退出,而子进程未退出

    • 孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作

    僵尸进程是父进程未退出,而子进程已退出

    • 当一个进程完成它的工作终止之后,它的父进程需要调用wait()或者waitpid()系统调用取得子进程的终止状态

    守护进程

    • 在Linux或者UNIX操作系统中在系统的引导的时候会开启很多服务,这些服务就叫作守护进程
    #include <unistd.h>
    int main() {
        static int a = 1;
        int b = 2;
        int *c = new int(3);
    
        pid_t pid;
        pid = fork();
    
        if (pid == -1) {
            cout << "fail";
            exit(-1);//echo $?
        } else if (pid == 0) {
            cout << getpid() << getppid() << endl;
            cout << ++a << ++b << ++*c << endl;
        } else {
            sleep(2);
            cout << getpid() << pid << endl;
            cout << a << b << *c << endl;
        }
    
        return 0;
    }
    

    进程间通信

    • 管道(共享文件)
    • 消息队列
    • 共享内存
    • 信号量
    • 套接字

    调度算法

    • 先来先服务(FCFS)
    • 短作业优先(SJF)
    • 优先级
    • 高响应比优先
    • 时间片轮转

    线程

    复制栈,共享代码段/数据段/堆

    多线程的创建与结束

    pthreadjoin/pthread_exit

    1. pthread_join一般是主线程来调用,用来等待子线程退出,因为是等待,所以是阻塞的,一般主线程会依次添加所有它创建的子线程
    2. ptbread_exit一般是子线程调用,用来结束当前线程
    3. 子线程可以通过pthread_exit传递一个返回值,而主线程通过 pthread_join获得该返回值,从而判断该子线程的退出是正常还是异常

    多线程同步

    临界资源

    • 互斥锁(mutex)
    #include<iostream>
    #include<pthread.h>
    using namespace std;
    
    int num = 2;
    pthread_mutex_t mutex_x = PTHREAD_MUTEX_INITIALIZER;
    
    void *f(void *args) {
        long int para = *(int *) args;
    
        for (int i = 0; i < 10; i++) {
            pthread_mutex_lock(&mutex_x);
            if (num > 0) {
                cout << pthread_self() << " " << num << endl;
                num--;
            }
            pthread_mutex_unlock(&mutex_x);
    
            int iRet = pthread_mutex_trylock(&mutex_x);
            if (iRet != EBUSY) {
                if (num > 0) {
                    cout << pthread_self() << " " << num << endl;
                    num--;
                }
                pthread_mutex_unlock(&mutex_x);
            }
        }
    
        pthread_exit((void *) para);
    }
    
    int main() {
        pthread_t tid[3];
        int para = 10;
        for (int i = 0; i < 3; i++) {
            pthread_create(&tid[i], nullptr, f, &para);
        }
    
        void *retval;
        for (int i = 0; i < 3; i++) {
            pthread_join(tid[i], &retval);
            cout << tid[i] << " " << (long int) retval << endl;
        }
    
        return 0;
    }
    
    • 条件变量(condition variable)(惊群现象)
    #include<pthread.h>
    using namespace std;
    
    int x = 10;
    int y = 20;
    pthread_mutex_t mutex_x = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t cond_x = PTHREAD_COND_INITIALIZER;
    
    void *f1(void *args) {
        pthread_mutex_lock(&mutex_x);
        if (x < y) {
            pthread_cond_wait(&cond_x, &mutex_x);
        }
        pthread_mutex_unlock(&mutex_x);
    
        pthread_exit((void *) 1);
    }
    
    void *f2(void *args) {
        pthread_mutex_lock(&mutex_x);
        if (x <= y) {
            x = 20;
            y = 10;
        }
        pthread_cond_signal(&cond_x);
        pthread_mutex_unlock(&mutex_x);
    
        pthread_exit((void *) 2);
    }
    
    int main() {
        pthread_t tid1, tid2;
        pthread_create(&tid1, nullptr, f1, nullptr);
        pthread_create(&tid2, nullptr, f2, nullptr);
    
        void *retval;
        pthread_join(tid1, &retval);
        pthread_join(tid2, &retval);
    
        return 0;
    }
    
    • 读写锁(reader-writer lock)
    pthread_rwlock_t rwlock_x = PTHREAD_RWLOCK_INITIALIZER;
    pthread_rwlock_rdlock(&rwlock_x);
    pthread_rwlock_tryrdlock(&rwlock_x);
    pthread_rwlock_wrlock(&rwlock_x);
    pthread_rwlock_trywrlock(&rwlock_x);
    pthread_rwlock_unlock(&rwlock_x);
    
    • 信号量(semphore)(多个线程,P(wait S--),V(signal S++))
    #include<semaphore.h>
    sem_t sem;
    sem_init(&sem, 0, 2);
    sem_wait(&sem);
    sem_trywait(&sem);
    sem_post(&sem);
    
    • 分离
        pthread_t tid;
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
        pthread_create(&tid, &attr, f, nullptr);
    
        pthread_create(&tid, nullptr, f, nullptr);
        pthread_detach(tid);
    

    • 生产者-消费者问题
    • 读者-写者问题
    • 哲学家进餐问题

    死锁

    • 互斥条件
    • 不剥夺条件
    • 请求和保持条件
    • 循环等待条件

    • 银行家算法(死锁避免算法)

    相关文章

      网友评论

          本文标题:进程/线程

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