复制代码

linux 大复习 进程2 通信

进程间通信方式
    1.匿名管道 父子进程之间进行通信 ;
        需要两个文件文件描述符 fd[2]
        小读 大写
    状态: 1.写关了 读 EOF
                2.没有数据读 ,阻塞
                3.读取关了,写会导致管道破裂
                4.没有地方写,阻塞 
    通过fcntl 控制·管道属性,fpathconf 测试管道缓冲区大小
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <unistd.h>
#include<sys/wait.h>
/*
int pipe(int pipefd[2]);

       
#include <fcntl.h>        
#include <unistd.h>

int pipe2(int pipefd[2], int flags);
*/
#define MSG "hello pipe\n"
int main()
{
    int fd[2];
    if(pipe(fd)==-1)
    {
        perror("pipe createt errno");
        exit(0);
    }
    
    
    pid_t pid =fork();
    if(pid==0)
    {
        //子进程 关闭读方向
        close(fd[0]);
            write(fd[1],MSG,strlen(MSG));
    /*    while(1)
        {
            write(fd[1],MSG,strlen(MSG));
        //    sleep(1);
        }
        */
    }
    else if(pid>0)
    {
        char buf[1024];
        close(fd[1]);
        while(1)
        {
            
        size_t tt = read(fd[0],buf,sizeof(buf));
        write(STDOUT_FILENO,buf,tt);
    }
        if(wait(NULL)==-1)
        {
                perror("the son  want to live more \n");
                exit(0);
        }
    }
    else
    {
        perror("the fork errno");
        exit(0);
    }
    return 0;
}
View Code

 

2.有名管道 通过mkfifo 创建管道文件
状态: 打开注意:先写打开才能正常都去打开 否则会产生阻塞
设置管道为阻塞 状态:1.没有数据 读 阻塞
                                   2.写操作 会产生拆开数据流,进行写入
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

      
/*
i  #include <sys/types.h>
       #include <sys/stat.h>

       int mkfifo(const char *pathname, mode_t mode);
*/
#define MSG "hello pipe\n"
int main(int argc ,char ** argv)
{
    int fd = mkfifo(argv[1],0664); 
    if(fd==-1)
    {
        perror("mkfifo errno :");
    }
    fd =open(argv[1],O_WRONLY);
        
    
    
     while(1)
         write(fd,MSG,strlen(MSG));
     perror("mkfifo errno :");
    
     
     
    return 0;
}
View Code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

      
/*
i  #include <sys/types.h>
       #include <sys/stat.h>

       int mkfifo(const char *pathname, mode_t mode);
*/
#define MSG "hello pipe\n"
int main(int argc ,char ** argv)
{
    char buf[1024];
    int fd = open(argv[1],O_RDONLY); 
    int tt = read(fd,buf,sizeof(buf));
    write(STDOUT_FILENO,buf,tt);    
    
    perror("mkfifo errno :");     
    close (fd); 
    return 0;
}
View Code

 

3.消息队列                            
            内核对象链表状态 由消息队列标识符表示
     有两个标准1.system V 和 posix
     首先
        1号消息队列 msgget 可以创建 两种消息队列 私有 或者公共     ipcs 
         2号消息队列为了移植 但是列表名字必须以 / 开始 并且需要挂在 才可见 
        # mkdir /dev/mqueue
        # mount -t mqueue none /dev/mqueue
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>


       
 
typedef struct msgbuf {
    long mtype;       
    char mtext[1024*10];     
}sz ;  

int main(int argc,char **argv)
{
     
    key_t key =  ftok("/home", 123);
 
    int msqid =msgget(key,0666|IPC_EXCL);
    if(msqid==-1)
    {
        perror("msgget errno ");
        exit(0);
    }
    char msgp[1024];
    //等于 0 第一条
    // >0   返回等于的消息
    //<0    返回第一个绝对值小于等于 的消息
     ssize_t ret =  msgrcv(  msqid, msgp,sizeof(msgp), 0, IPC_NOWAIT);
     if(ret==-1)
    {
        perror("mshrcv errno");
        exit(0);
    }
    
    printf("%s \n",((struct msgbuf*)msgp)->mtext);
     
    
    
    
    
    
    
    
    
    
     
    return 0;
}
View Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h> 
#include <unistd.h>
#include <fcntl.h>            
#include <sys/stat.h>         
#include <mqueue.h>

/*
struct mq_attr {
     long mq_flags;        
     long mq_maxmsg;      
     long mq_msgsize;     
     long mq_curmsgs;     
 }; 
 */
int main()
{
//        printf("%d\n",mq_unlink("/tt"));
    mqd_t mqdes =  mq_open("/tt", O_RDWR|O_CREAT|O_EXCL);
    //mqd_t mqdes =  mq_open("/tt", O_WRONLY);
  if(mqdes ==-1)
     {
         perror("mqopen errno ");
         exit(0);
     }
     printf("%d\n",mqdes);
     
 
  
     char buf[]="hello world \n ";
    if(mq_send(mqdes, buf,sizeof(buf)    , 1)==-1)
  {
         perror("mqopen errno ");
         exit(0);
     }
     
     struct mq_attr attr;
     memset(&attr,0,sizeof(attr));
    if(mq_getattr(mqdes, &attr)==-1)
  {
         perror("mq_getattr errno ");
         exit(0);
     }
    printf("mq_flags : %ld\t mq_maxmsg : %ld\t mq_msgsize : %ld\t mq_curmsgs : %ld\n"
    ,attr.mq_flags,attr.mq_maxmsg,attr.mq_msgsize,attr.mq_curmsgs);
            
    printf("%d\n",mq_close(  mqdes));
    return 0;
    
}
View Code

 

4.共享内存映射  mmap  munmap
        产生共享内存映射,选择模式 共享内存 私人映射 
        共享内存 进行通信 ,私人映射
        1、用于进程间通信时,一般设计成结构体,来传输通信的数据
        2、进程间通信的文件,应该设计成临时文件(即创建文件,使用文件,删除文件)
        3、 当报总线错误时,优先查看共享文件是否有存储空间
 
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> 
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>



int main()
{
    int fd = open("a", O_RDWR); 
 char *  ps = mmap(NULL,120, PROT_WRITE, MAP_SHARED,
      fd, 0);
 
 if(ps==NULL)
 {
     perror("mmap errno");
    exit(0);
}
for(int i=0;i<10;i++)
    ps[i]='h';
 //write(STDOUT_FILENO,ps,off);
 munmap(ps,120);

    
    
    return 0;
}
View Code

 

5.信号量 你需要信号量进行开始 或者阻塞
    使用范围 进行 PV 操作
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h> 
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <semaphore.h>
#include <errno.h>

int sem_create(key_t key)
{
    int semid = 0;
    semid =  semget(  key, 1 , 0666|IPC_CREAT | IPC_EXCL);
     if(semid ==-1)
     {
         if(errno ==EEXIST)
         {
             printf("the sem  has existed \n");
             semid = semget(  key, 1 ,0666); 
         }
     }
     return semid;     
}

union semun {
int              val;     
struct semid_ds *buf;     
unsigned short  *array;   
struct seminfo  *__buf;   
};

int sem_setval(int  semid,int val )
{
    int ret =0;
    union semun su;
    su.val =val;
     ret = semctl(semid, 0 , SETVAL, su);
     return ret; 
}
int sem_getval(int  semid  )
{
 
    union semun su; 
  semctl(semid, 0, GETVAL, su);
     return su.val; 
}
/*
struct sembuf
{ 
    unsigned short sem_num;   
    short          sem_op;    
    short          sem_flg;   
};
*/
int    sem_p(int semid)
{
    struct sembuf sops={0,-1,0/*    IPC_NOWAIT 阻塞  SEM_UNDO 回退    */}; 
    int ret = semop(  semid, &sops, 1);
    if(ret==-1)
    {
        perror("sem_p errno");
        exit(0);
    }
    return 0;
} 
int sem_v(int semid)
{
    struct sembuf sops={0,1,0}; 
    int ret = semop(  semid, &sops, 1);
    if(ret==-1)
    {
        perror("sem_p errno");
        exit(0);
    }
    return 0;
}
int main()
{
    int ret;
    
    key_t key  = ftok("/tt", 1);
    int semid =sem_create(key);
    if(semid <0 )
    {
        perror("sen_create errno ");
        exit(0);
    }
    //几个信号量 才能运转起来
    
    //设置信号量数值
    ret = sem_setval(semid,0);
 
    ret = sem_getval(semid );
    printf("sem_getval %d \n",ret);
    
    //加减锁
    sem_p(semid);
    printf("hello sem \n");
    sem_v(semid);
    
    
    
    
    
    printf("semid %d \n",semid);
    
    
        
}
 
View Code

 

 
 
 
 
 
 
 
 
    
 
posted @ 2018-03-26 20:24  pg633  阅读(165)  评论(0编辑  收藏  举报