Linux 进程学习

1、linux进程间通讯
        继承unix进程间通讯:管道 信号
        AT&T :system V IPC 通讯进程只能在单个计算机 :信号量  消息队列 共享内存
        BSD:形成了基于socket的进程间通讯机制 TCP/IP
2、管道
        (1)无名管道:父子进程
                 #include <unistd.h>

int pipe(int pipefd[2]);
                 创建一个管道
                 fd[0]:读端
                 fd[1]:写端
                返回值:
                        0:成功
                        -1:失败
                注意:(1)当管道已经满了 write pipe 会阻塞
                       (2) 当管道为空   read pipe 会阻塞

(2)有名管道:任何进程之间
        #include <sys/types.h>
        #include <sys/stat.h>
                int mkfifo(const char *pathname, mode_t mode);
3、信号
        信号在软件层次上对中断的一种模拟 异步通讯方式
        中断:对cpu上的中断 (硬件)
        信号:对进程的中断 (软件)
        (1)信号的来源
                (1)程序执行错误 如 内存访问越界
                (2)其他进程发送
                (3)通过控制终端发送 ctrl + c;
                (4)子进程结束向父进程发送信号 SIGCLD
                (5)定时器SIGALRM
        (2)信号
                kill -l 查看当前系统所有的信号
        (3)信号处理方式
                忽略信号:对信号不做任何处理
                捕捉信号:定义处理函数 当信号发生的时候 执行相应的处理函数  
                缺省操作:在linux系统中间都规定了默认操作
        (4)信号的发送与捕捉
                 #include <sys/types.h>
                 #include <signal.h>

int kill(pid_t pid, int sig);
                        pid:接受信号的进程的PID
                        sig:信号
                返回值:0:成功
                        -1:出错
                 int raise(int sig);
                 //kill(getpid(),SIGSTOP);
                    给进程本身发送信号

(5)定时器的信号捕捉       
                unsigned int alarm(unsigned int seconds);
                进程定时器
                定时时间到 发送SIGALRM
                SIGALRM:默认操作:终止进程
                返回值:
                        在调用之前 如果已经设置过闹钟 返回上一次的剩余时间
                        否则返回0
                        -1:出错
                int pause(void);
                暂停进程
                当收到信号时 会唤醒进程继续执行
        (6)信号处理
                #include <signal.h>
                typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);
       
                参数:
                        signum:信号
                        handler:SIG_IGN:忽略该信号
                                SIG_DFL:采用默认方式处理信号
                                自定义的信号处理函数的指针
                返回值:返回一个指向信号处理函数的地址

1)父进程捕捉子进程的信号
                2)从终端输入文字再次输出到终端,如果3s没有输入就输出提示
                        //SIGALRM
                        alarm()和signal()
4、信号的阻塞处理       
        (1)通知系统内核停止向进程发送指定的信号       
        (2)内核对进程接收到的相应的信号进行缓存
       (3)当进程解除相应的信号的阻塞

设置阻塞的原因:
                (1)正在执行信号处理函数时有其他的信号到来
                (2)信号处理函数和其他进程对某个共享区域进行读写
                sigset_t:信号集
          int sigemptyset(sigset_t *set);
          把信号集合清空

int sigfillset(sigset_t *set);
          把信号集合填满
          int sigaddset(sigset_t *set, int signum);
          把对应的信号加到阻塞信号集合中

int sigdelset(sigset_t *set, int signum);
          把对应的信号从阻塞信号集合中删除       
          int sigismember(const sigset_t *set, int signum);
          判断信号是否是在阻塞信号集合中
          int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
          //设置阻塞信号集合

how:设置信号阻塞掩码的方式
                          SIG_BLOCK:阻塞信号集
                        SIG_UNBLOCK:解除信号集
                        SIG_SETMASK:设置阻塞掩码
         oldset:旧的阻塞集合
         int sigpending(sigset_t *set);
         //获取阻塞的信号 未决信号

int flag = 0;
        int flag = 1;
        while(flag == 0){
          int sigsuspend(const sigset_t *mask);
        }
          //等待信号  
          (1)设置信号掩码并阻塞进程
         (2)收到信号 恢复原来的屏蔽字
          (3)调用进程设置的信号处理函数
         (4)等待信号处理函数返回后 sigsuspend()返回
          原子操作
          pause() -----等待信号(阻塞的信号除外)
5、消息队列
        (1)消息的列表
                队列ID
                消息ID
         (2)创建
                 #include <sys/types.h>
                #include <sys/ipc.h>
                #include <sys/msg.h>

int msgget(key_t key, int msgflg);
                key:指定的ID来生成队列ID key:ftok()通过转换文件来获取
                msgflg:IPC_CREAT:创建新的消息队列
                       IPC_EXCL:存在报错
                       IPC_NOWAIT:非阻塞
                返回值:返回队列ID
                #include <sys/types.h>
                #include <sys/ipc.h>

key_t ftok(const char *pathname, int proj_id);
                    功能:获取key
                    pathname:文件名---->inode节点号
                    proj_id:自己指定

由inode节点号和proj_id合成

65538:0x10002  
                    
                    38:0x26

key: 0x2610002

(4)接收消息
                 ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
                 参数:
                         msqid:消息队列ID ----- msgget()
                        msgp:消息的缓冲区
                        msgsz:消息结构的大小
                        msgtyp:0:接收消息队列中的第一个消息
                               大于0:接收消息队列中第一个为msgtyp的消息
                               小于0:接收消息队列中第一个不小于msgtyp的绝对值由最小的消息
                        msgflg:
                                0:忽略
                                MSG_NOERROR:接收的消息大于size 则消息就会截短到size字节 不通知消息发送进程
                                IPC_NOWAIT:没有指定类型的消息 就会返回错误ENOMSG
                返回值:实际接收的字节数
                        会删除对应的消息
        (5)发送消息
                 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
                 参数:
                         msqid:消息队列ID ----- msgget()
                        msgp:发送的消息缓冲区
                        struct msgbuf{
                                long mtype;//消息类型
                                char mtext[1];//消息内容
                        };
                        msgsz:消息内容的大小
                        msgflg:
                                IPC_NOWAIT:发送条件不满足的时 就会立即返回

a):队列消息已经满了
               
        创建2个子进程 父进程负责发送 子进程1:发送类型为1的消息        子进程2:发送消息类型为2的消息
        子进程1接收类型为1的消息
        子进程2接收类型为2的消息

(5)控制函数
          int msgctl(int msqid, int cmd, struct msqid_ds *buf);

msqid:消息队列ID
          cmd:
                  IPC_STAT:获取struct msqid_ds结构 保存到buf
                IPC_SET:设置struct msgqid_ds结构
                IPC_RMID:删除消息队列
           buf:存储struct msqid_ds结构

返回值:成功:0(IPC_STAT,IPC_SET,IPC_RMID)
                    失败:-1

上一篇:Swift学习——A Swift Tour 枚举和结构体


下一篇:C++中的关键知识点(汇总)