Linux进程间的通信

一、无名管道Pipe

示意图:

Linux进程间的通信_第1张图片

1)管道就相当于队列的数据结构;

2)管道只适合半双工的通信方式;

3)只能用于具有亲缘关系的进程间通信;

4)管道操作不能同时读和写;读的时候要关闭写端;写的时候要关闭读端;

函数:

#include
int pipe(int pipefd[2]);

说明:

参数:文件描述符:pipefd[0]   是读;pipefd[1]   是写;

返回值:0     成功;其他       失败;



举例:

#include
#include
#include
#include

int main()
{
        int fd[2];
        int pid;
        char *w_count="hello world!";
        char r_count[255];
        if(pipe(fd)!=0)
        {
        printf("create pipe fail.\n");
        return -1;
        }
        if((pid=fork())<0)
        {
                printf("create process  fail.\n");
                return -1;
        }

        else if(pid>0)
        {
                close(fd[0]);
                write(fd[1],w_count,strlen(w_count));
                close(fd[1]);
                wait();
        }
        else
        {
                sleep(2);//等待父进程写操作;
                close(fd[1]);
                read(fd[0],r_count,255);
                close(fd[0]);
                printf("child read:%s\n",r_count);
        }
        return 0;
}

运行结果:

[root@localhost ~]# ./pipe
child read:hello world!


二、有名管道FIFO

在shell中,我们可以用mkfifo命令建立一个管道文件:“mkfifo   myfifo”;

Fifo突破了pipe只能在父子进程中通信的局限性;这两个不相关的进程通过管道文件建立通信;

函数:

#include
#include
int mkfifo(const char *pathname, mode_t mode);

功能:建立管道文件;然后就可以对文件进行读写操作了;

参数:pathname是路径名称,mode是建立方式;

返回值:0      创建成功;-1       失败;


三、信号

1.(1)

#include
int raise(int sig);

功能:向进程本身发送命令;

(2)

 #include
unsigned int alarm(unsigned int seconds);


(3)

 #include
 #include
  int kill(pid_t pid, int sig);


(4)

#include
int pause(void);


2.简单信号处理

  #include
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);


该函数可以还原为:

#include
void (*signal(int signum, void (*handler))(int)))(int);

第一个参数指定信号的值,第二个参数指定针对前面信号值的处理,可以忽略该信号(参数设为SIG_IGN);可以采用系统默认方式处理信号(参数设为SIG_DFL);也可以自己实现处理方式(参数指定一个函数地址)。

如果signal()调用成功,返回最后一次为安装信号signum而调用signal()时的handler值;失败则返回SIG_ERR。传递给信号处理例程的整数参数是信号值,这样可以使得一个信号处理例程处理多个信号。

举例:

#include
#include
#include

void sig_handler(int sig_no)
{
        if(sig_no==SIGINT)
        {
                printf("get SIGINT\n");

        }
        else if(sig_no==SIGQUIT)
        {
                printf("get SIGQUIT\n");
        }
}

int main()
{
        printf("wait for signal\n");
        signal(SIGINT,sig_handler);
        signal(SIGQUIT,sig_handler);
        pause();
        return 0;

}





3.信号集合函数处理



四、共享内存


1.

#include

 #include

int shmget(key_t key, size_t size, int shmflg);

功能:开辟内存;

返回值:成功时返回shmID,失败时返回-1 并且记录到error;


2.

 #include
 #include


void *shmat(int shmid, const void *shmaddr, int shmflg);

功能:映射;也可以用memcpy操作;
返回值:成功时返回地址,失败时返回(void*)-1 并且记录到error;

  int shmdt(const void *shmaddr);

功能:关闭映射;

返回值:成功时返回0,失败返回-1;


int shmctl(int shmid, int cmd, struct shmid_ds *buf);

功能:操作内核态的共享空间;

返回值:成功时返回0,失败时返回-1;


举例:/*建立并写入共享内存*/

#include
#include
#include
#include
#include

int main()
{

        char contents[]="hello  world";
        void *share_mem=(void*)0;
        int shmid=shmget(123,2046,IPC_CREAT|0666);
        if(shmid!=-1)
        {
                share_mem=shmat(shmid,NULL,0);
                if(share_mem!=(void*)-1)
                {
                        memcpy(share_mem,contents,12);
                        printf("save successed");
                        shmdt(share_mem);
                }
                else
                {
                        perror("shmat:");
                }
        }
        else
                perror("shmget:");
        return 0;
}


执行结果:

[root@localhost ~]# ./chm_write
save successed


/*从共享内存中读出*/

#include
#include
#include
#include
#include

int main()
{

        void *share_mem=(void*)0;
        int shmid=shmget(123,2046,IPC_CREAT|0666);
        if(shmid!=-1)
        {
                share_mem=shmat(shmid,NULL,0);
                if(share_mem!=(void*)-1)
                {
                        printf("get share memery:%s\n",(char*)share_mem);
                        shmdt(share_mem);
                }
                else
                {
                        perror("shmat:");
                }
        }
        else
                perror("shmget:");
        return 0;
}

执行结果:

[root@localhost ~]# ./chm_read
get share memery:hello  world

五、消息队列


1.

#include
#include
#include

int msgget(key_t key, int msgflg);

功能:得到消息队列号;

2.

 #include
 #include
 #include

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:发送消息;

消息结构体:struct msgbuf {
               long mtype;       /* message type, must be > 0 */
               char mtext[1];    /* message data */
           };

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
                      int msgflg);

功能:接收消息;

注意:消息被取出来后就不存在了;

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

功能:消息控制操作;

举例:

/*msg_send.c*/

#include
#include
#include
#include
#include

struct msgbuf
{
        long mtype;
        char mtext[255];
} ;

int main()
{
        struct msgbuf mybuf;
        mybuf.mtype=1;
        strcpy(mybuf.mtext,"hello world");
        int msgqid=msgget(2345,IPC_CREAT|0666);
        if(msgqid!=-1)
        {
                if(msgsnd(msgqid,&mybuf,sizeof(mybuf.mtext),0)!=-1)
                {
                        printf("send message successed\n");
                }
                else
                        perror("msgsend error\n");
        }
        else
                perror("msgget error\n");
        return 0;
}
~
运行结果:

[root@localhost app_code]# ./msg_send
send message successed


/*msg_recive.c*/

include
#include
#include
#include
#include

 struct msgbuf
{
        long mtype;
        char mtext[255];
};

int main()
{
        struct msgbuf mybuf;
        int msgqid=msgget(2345,IPC_CREAT|0666);
        if(msgqid!=-1)
        {
                if(msgrcv(msgqid,&mybuf,sizeof(mybuf.mtext),0,0)!=-1)
                {
                        printf("receive message :%s\n",mybuf.mtext);
                }
                else
                        perror("msgrcv error\n");
        }
        else
                perror("msgget error\n");
        return 0;
}

运行结果:

[root@localhost app_code]# ./msg_resv
receive message :hello world


六、信号量

1.      

 #include
 #include

#include

int semget(key_t key, int nsems, int semflg);

功能:得到建立信号量;

参数:key:

nsems是要开辟的信号个数;

semflg是标志;


int semop(int semid, struct sembuf *sops, unsigned nsops);

功能:信号量的操作;

参数:semid是信号ID;

nsops是信号操作数量;

struct sembuf

{

unsigned short sem_num;  /* semaphore number */
           short          sem_op;   /* semaphore operation */
           short          sem_flg; 

}


 int semctl(int semid, int semnum, int cmd, ...);

功能:设置信号量;


举例:

#include
#include
#include
#include
#include

int semid;
struct sembuf sem_down={0,-1,0};
struct sembuf sem_up={0,1,0};

void down()
{
        semop(semid,&sem_down,1);
}

void up()
{
        semop(semid,&sem_up,1);
}

int main()
{
        int semid=semget(123,1,IPC_CREAT|0666);
        if(semid!=-1)
        {
                semctl(semid,1,SETVAL);
                down();

                printf("hello world\n");
                sleep(10);

                up();

        }

        else
        {
                perror("semget error:");
        }

        return 0;
}
      
运行结果:

[root@localhost ~]# ./sembol
hello world

你可能感兴趣的:(Linux应用程序)