您的位置:首页 > 运维架构 > Linux

Linux进程通信

2016-07-05 20:18 399 查看

一、进程通信

(一)、Linux进程间通信有以下几个版本:

1、UNIX进程间通信

2、基于system进程间通信

3、基于POSIX进程间通信

(二)、进程间通信方式

1、管道(pipe)与有名管道(FIFO)

2、信号(singal)

3、消息队列

4、共享内存

5、信号量

6、套接字(sockfd)

(三)、管道

特点:

1、单向,先进先出,尾部写,头部读

2、读完变删除

3、当管道数据已满或管道内无数据时,进程会阻塞

无名管道:父子进程之间的通信

有名管道:任意两个进程之间的通信

4、无名管道创建方式:

int pipe(int fields[2]);

此函数创建两个文件描述符:fields[0]、fields[1],第一个文件以只读方式打开,为读取端,将fields[0]的文件读入管道。第二个文件以只写方式打开,将管道内的文件写入fields[1];

注意点:
应该在fork之前先创建管道。如图释:



例子:
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int pipe_fd[2];
if(pipe(pipe_fd)<0)
{
printf("pipe create error\n");
return -1;
}
else
printf("pipe create success\n");
close(pipe_fd[0]);
close(pipe_fd[1]);
}如果是父进程给子进程发消息:

父进程:

先close(fd[0]);把读关掉,先往里写

子进程:

先close(fd[1]);

5、有名管道创建方式

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

pathname:FIFO文件路径    mode:该文件的权限

(四)、共享内存(最快的方式)

头文件:#include <sys/shm.h>



创建共享内存两步骤:

1、创建共享内存:shmget    开辟内存

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

key:两个键值:0/IPC_PRIVATE

如果成功,返回共享内存标识符,如果失败,返回-1

2、映射共享内存:shmat    程序共享虚拟地址

char shmat(int shmid,char *chmaddr,int flag);

shmid:内存标识符    flag:置0

一旦创建了一个FIFO,就可用open打开它,一般的文件访问函数(close、read、write等)都可用于FIFO

(五)、消息队列

头文件:#include <sys/msg.h>

可传送有格式的字节流

消息队列的创建

1、创建消息队列需要先申请键值

key_t ftok(char *pathname,char proj);

pathname:文件名    proj:随机取

成功返回键值

2、int msgget(int key_t,int msgflg);

key_t:键值    msgflag:IPC_CREATE

返回值:消息队列描述符

3、int msgsnd(int msqid,struct msgbuf *msgp,int msgsz,int msgflg);

msqid:消息队列描述符    

msgp:

struct msgbuf

{

    int type;    //不可变

    char buffer[1025];    //发的消息

};

msgsz:消息大小

msgflg:IPC_NOWAIT(不堵塞)

4、int msgrcv(int msqid,struct msgbuf *msggp,int msgsz,long msgty,int msgflg);

msqid:消息队列描述字

msgp:

struct msgbuf

{

    int type;    //不可变

    char buffer[1025];    //发的消息

};

msgsz:消息大小

msgty:第几个结构体

msgflg:IPC_NOWAIT

二、信号

(一)、信号处理方式:

1、忽略(其中SIGKILL和SIGSTOP不可忽略)

2、执行用户希望的动作

3、执行系统的默认动作

(二)、kill和raise

   #include <sys/types.h>

   #include <signal.h>

   int kill(pid_t pid, int signo)

   int raise(int signo)

kill的pid参数有四种不同的情况:

1、pid>0

   将信号发送给进程ID为pid的进程。

2、pid == 0

   将信号发送给同组的进程。

3、pid < 0

   将信号发送给其进程组ID等于pid绝对值的进程。

4、pid ==-1

 将信号发送给所有进程。

(三)、alarm

#include <signal.h>

unsigned int alarm(unsigned int seconds)

参数为经过多少秒发出警告

(四)、singal

例子:不可强制退出

#include <stdio.h>

#include <signal.h>

void func(int signal)

{

    if(signal == SIGINT)

    {

        printf("ctrl + c!\n");

    }

}

int main()

{

    signal(SIGINT,func);

    while(1)

    {

        printf("hello wrold!\n");

        pause();

    }

}

三、多线程编程

(一)、多线程特点

1、共享数据段,线程之间彼此切换所需的时间短,通信方式简单,使CPU系统更加有效,改善程序结构

(二)、线程的进程的区别

(三)、相关API:

头文件:#include <pthread.h>

1、创建线程

pthread_t id;

pthread_create(&id,NULL,print_msg,NULL);

可以重复创建,重复调用,谁先创建谁先执行,创建线程的程序一结束,所有子线程结束

2、线程等待函数

作用:主线程等待子线程结束了主线程才可结束

pthread_join(id,NULL);

3、pthread_exit(NULL)

在子线程中将该线程结束

4、第四个参数的使用

(四)、线程同步

保证线程同步的三种方法

1、互斥量(互斥锁)    2、信号灯    3、多量变量

过程:

全局变量中,先定义一把锁:pthread_mutex_t mutex;

主线程中初始化互斥锁:pthread_mutex_init(&mutex,NULL);

上锁:int pthread_mutex_lock(&mutex);

解锁:int pthread_mutex_unlock(&mutex);

例子:

#include <stdio.h>
#include <pthread.h>

int ticket = 10;

pthread_mutex_t mutex;

void sell_ticket(void * arg)
{
while(1)
{
pthread_mutex_lock(&mutex);

if(ticket > 0)
{
sleep(1);
}
else
{
pthread_mutex_unlock(&mutex);
break;
}

printf("Left tickets:%d\n",--ticket);

pthread_mutex_unlock(&mutex);
}
}

int main()
{
pthread_t id1;
pthread_t id2;
pthread_t id3;

pthread_mutex_init(&mutex,NULL);

pthread_create(&id1,NULL,(void *)sell_ticket,NULL);
pthread_create(&id2,NULL,(void *)sell_ticket,NULL);
pthread_create(&id3,NULL,(void *)sell_ticket,NULL);

pthread_join(id1,NULL);
pthread_join(id2,NULL);
pthread_join(id3,NULL);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Linux进程通信