C++面试 一 进程和线程

1. 进程间的通信方法

    1. 管道 pipe

        管道也是一种文件,有两种方式:匿名管道和命名管道

        管道文件大小一般为4K或64K

        匿名管道:int fd[2]; if(pipe(fd) < 0),只有父子进程可以使用,单向数据通信,不需要考虑同步和互斥,父子进程退出时,管道就结束了,生命周期是进程。

        命名管道:int mkfifo(const char* pathname, mode_t mode); 管道路径 访问权限umask

        创建文件后,服务端和客户端分别使用open打开文件,只读或只写

        管道缺点,是基于文件系统的,因此不管是度还是写,都要求访问磁盘系统进行I/O操作,速度很慢,不适合多client的结构

    2. 消息队列 mgget, ipcs -q 可以查看消息队列的状态

        消息队列是一个类似链表的结构存在于内核的内存中,进程结束之后,消息队列还可能存在

        管道是数据流式存取,消息队列是数据块式存取

       创建消息队列 int msgget(key_t key, int msgflg) 返回消息队列id

        key标识一个消息队列, msgflg IPC_CREAT已存在就打开,不存在就创建

        把id和path绑定,获取key key_t ftok(const char* pathname, int proj_id)

        发送消息 int msgsnd(int msgid, const void* msgp, size_t msgsz, int msgflg)

        接收消息 int msgrcv(int msgid, const void* msgp, size_t msgsz, int msgflg)

    3. 信号 signal,可以通过kill -l查看所有的信号

        信号可能由硬件产生、由进程发送、异常

        信号由操作系统处理,信号不一定会被立即处理,会在适当的时候,比如中断返回,内核态返回用户态的时候。

        没有0信号,没有32、33信号,31之前是普通信号,后面是实时信号

        信号的三种处理方式:忽略,默认会终止一个进程,自定义处理

        sighandler_t signal(int signum, sighandler_t handler) handler是一个函数指针

        int raise(int signo) 只能给自己进程发送信号

        int kill(pid_t pid, int signo) 给对应的pid发送signo信号

    4. 信号量 semget

        多用于进程间的同步和互斥

        同步:是指在互斥的基础上,通过某种机制使访问者对资源能够有序访问。

        互斥:是指某一个资源同一时刻只允许一个访问者对其进行访问,具有唯一性和排他性,但是互斥不能限制访问顺序,即互斥是无序的

        创建信号量 int semget(key_t key, int nsems, int semflg)

        PV操作 int semop(int semid, struct sembuf* sops, unsigned nsops)

    5. 共享内存 shmget,通过ipcs -m 可以查看当前共享内存的状态

        管道是文件,操作慢,消息队列创建有消耗,共享内存效率高,速度快

        创建共享内存 int shmget(key_t key, size_t size, int shmflg)

        连接共享内存 void* shmat(int shmid, const void* shmaddr, int shmflg)

        断开共享你村 int shmdt(const void* shmaddr)

    6. 共享文件映射 mmap

    7. 套接字 socket

2. 线程和进程有什么区别

    根本区别:进程是分配和管理资源的基本单位,线程是进程任务调度和执行的基本单位。

    开销方面:每个进程都有独立的代码和数据空间,进程之间切换会有较大的开销,线程可以看做轻量级的进程,统一进程内的线程共享代码和数据空间,每个线程有自己独立的运行栈和程序计数器,线程之间切换开销小。

    所处环境:操作系统中能同时运行多个进程,同一进程内可以有多个线程同时执行。

    地址空间:同一进程的线程共享本进程地址空间,而进程之间则是独立的地址空间

    资源拥有:同一进程内的线程共享本金诚的资源,如内存、I/O、CPU等,但是进程之间的资源是独立的

    线程是处理器调度的基本单位,但进程不是

    进程和线程都可以并发执行

    优缺点:

        线程执行开销小,但是不利于资源的管理和保护

       进程执行开销大,但是能够很好的进行资源管理和保护

    什么时候用多进程,什么时候用多线程?

        需要频繁创建和销毁的用多线程,进程创建和销毁开销大

        线程切换速度快,需要大量计算,操作耗时的任务时,切换频繁时,使用多线程

        多机分布的用多进程,多核分布的用多线程

        需要更稳定安全时,使用多进程,需要速度时,使用多线程

4. 线程同步方法有哪些

    1. 互斥锁mutex

        初始化 int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutex_attr* attr)

        加锁 int pthread_mutex_lock(phtread_mutex_t* mutex) 还有trylock

        解锁 int pthread_mutex_unlock(pthread_mutex_t* mutex)

        销毁 int pthread_mutex_destroy(phtread_mutex_t* mutex)

    2. 条件变量cond

        初始化 int pthread_cond_init(pthread_cond_t* cond, pthread_cont_attr_t* attr)

        等待条件成立 int pthread_cond_wait(cond, mutex)

        激活条件变量 phtread_cond_signal phtread_cond_broadcast

        销毁 phtread_cond_destroy

    3. 信号量

        初始化 sem_init(sem_t* sem, int pshare, unsigned int value)

        等待 sem_wait(sem_t* sem)

        释放 sem_post(sem_t* sem)

        销毁 sem_destroy(sem_t* sem)

        互斥锁是为了上锁而设计的,条件变量是为了等待而设计的,信号量即可用于上锁,也能用于等待,因此可能导致更多的开销和复杂性

    4. 读写锁

        适合读次数比写次数多得多的情况,以读模式锁时,可以共享,以写模式锁住时意味着独占,所以读写锁又叫 共享-独占锁

    5. 自旋锁spinlock

        自旋锁是在多个CPU系统中,当一个CPU访问被自旋锁保护的临界区时,自旋锁被锁上,其他要访问这个临界区的CPU只能等待,直到前面的CPU访问完开锁。

        自旋锁上锁后等待进程将进行忙等待而不是睡眠阻塞,忙等待浪费了处理时间,但是时间通常很短,1ms以下,信号量是让线程睡眠阻塞,

    6. 屏障barrier

        屏障是linux中协调多个线程并行工作的同步机制,屏障允许每个线程等待,直到所有合作线程达到某一点,然后继续从该点执行, pthread_join是一种屏障,但只允许一个线程等待。

        pthread_barrier_int

        pthread_barrier_wait

5. 死锁

    死锁是两个以上的进程在执行过程中, 由于竞争资源或彼此通信造成的一种阻塞,若无外力作用,他们都无法继续执行下去

    死锁产生的4个必要条件:

  1. 互斥条件:进程要求对所分配的资源进行排他控制,在一段时间内某资源仅能被一个进程占用
  2. 请求和保持:当进程因请求资源而阻塞时,对已获得的资源保持不放
  3. 不剥夺条件:进程已获得的资源在未使用完之前,不能剥夺,只能在使用完时自己释放
  4. 环路等待条件:在发生死锁时,必然存在一个进程-资源的环形链

    怎么防止死锁

        资源一次性分配:一次性分配所有资源,这样就不会再有请求了(破坏请求)

        只要有一个资源得不到分配,就不给这个进程分配其他资源(破坏保持)

        可剥夺资源:某进程获得了部分资源,但得不到全部资源,释放已有资源(破坏不可剥夺)

        资源有需分配:系统给每类资源编号,每个进程按编号递增顺序请求资源,释放相反(破坏环路等待)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值