数据库:动态库.os 静态库.a /lib /usr/lib
不同1. .a .so
2.使用时刻不同 静态编译 动态运行
3.可移植性 静态可移植
单工通信:数据的传送方向为单向
半双工通信:数据的传送方向为双向,但不同时
全双工通信:数据的传送方向为双向且同时
无名管道是用pipe创建的一个内核文件,用于具有亲缘关系的进程间的通信。
int pipe(int pipefd[2]);
pipefd[2]:数组,fd[0]用来标识读管道文件
fd[1]用来标识写管道文件
返回值:0 成功;-1 失败
#include
#include
#include
#define BUF_SIZE 20
int main()
{
//1.pipe
int fd[2] = {0};
if(0 != pipe(fd))
{
printf("create pipr error!!\r\n");
return -1;
}
printf("1:create pipe ok!\r\n");
//2.fork
pid_t pid = -1;
pid = fork();
if(-1 == pid)
{
return -1;
}
char buf[BUF_SIZE] = {0};
if(0 == pid)
{
//child write
close(fd[0]);
printf("child process!\r\n");
strcpy(buf,"child to parent");
write(fd[1],buf,BUF_SIZE);
}
else
{
//parent read
close(fd[1]);
printf("parent process!\r\n");
read(fd[0],buf,BUF_SIZE);
printf("parent read:%s\r\n",buf);
}
}
1.只能用于具有亲缘关系的进程间通信
2.是一种单工通信模式(理论上是双工的,但是通信双方的收发顺序不好控制,通常用作单工)
3.无名管道的数据存放在内存中,管道中的数据读走后就不存在了,无名管道只存在于内核中,在文件系统中不可见
有名管道是用mkfifo创建的一个内核文件,用于任意两个进程之间的通信,管道文件在文件系统中可见。
int mkfifo(const char *pathname, mode_t mode);
作用:创建一个有名管道文件
*pathname:有名管道文件的名称
mode:文件权限
返回值:0 成功; -1 失败
ret = mkfifo("fifo",0666);
if(ret<0&&EEXIST!=errno)-->创建文件失败并且该文件不存在
{
return -1;//创建文件失败
}
创建文件失败但是该文件存在==>创建文件成功
A:
1.mkfifo ---> 有名称
2.open
3.write
B:
1.mkfifo
2.open
3.read
单工
#include
//#include
#include
#include
#include
#include
#include
#define BUF_SIZE 20
int mian()
{
//1.mkfifo
int ret = -1;
ret = mkfifo("fifo",0666);
if(ret < 0&& EEXIST != errno)
{
return -1;
}
printf("create fifo ok!---\r\n");
//2.open
int fd = open("fifo",O_WRONLY,0666);
if(-1 == fd)
{
return -1;
}
printf("2:open fifo ok!--------\r\n");
//3.write
char buf[BUF_SIZE] = {0};
strcpy(buf,"hello 22101");
write(fd,buf,BUF_SIZE);
//4.close
close(fd);
return 0;
}//A
#include
//#include
#include
#include
#include
#include
#include
#define BUF_SIZE 20
int mian()
{
//1.mkfifo可要可不要
int ret = -1;
ret = mkfifo("fifo",0666);
if(ret < 0&& EEXIST != errno)
{
return -1;
}
printf("create fifo ok!---\r\n");
//2.open
int fd = open("fifo",O_RDONLY,0666);
if(-1 == fd)
{
return -1;
}
printf("2:open fifo ok!--------\r\n");
//3.read
char buf[BUF_SIZE] = {0};
read(fd,buf,BUF_SIZE);
printf("read ok!buf = %s\r\n",buf);
//4.close
close(fd);
return 0;
}//B
双工
#include
//#include
#include
#include
#include
#include
#include
#define BUF_SIZE 20
int mian()
{
//1.mkfifoa
int ret = -1;
ret = mkfifo("fifoa",0666);
if(ret < 0 && EEXIST != errno)
{
return -1;
}
printf("create fifoa ok!---\r\n");
//mkfifob
ret = mkfifo("fifob",0666);
if(ret < 0 && EEXIST != errno)
{
return -1;
}
printf("create fifob ok!---\r\n");
//3.open fifoa
int fdw = open("fifoa",O_WRONLY,0666);
if(-1 == fdw)
{
return -1;
}
printf("3:open fifoa ok!--------\r\n");
//4.open fifob
int fdr = open("fifob",O_RDONLY,0666);
if(-1 == fdr)
{
return -1;
}
printf("4:open fifob ok!--------\r\n");
char buf[BUF_SIZE] = {0};
while(1)
{
//5.write
memset(buf,0,BUF_SIZE);
fgets(buf,BUF_SIZE,stdin);//get(buf);
write(fdw,buf,BUF_SIZE);
//6.read
memset(buf,0,BUF_SIZE);
read(fdr,buf,BUF_SIZE);
printf("b->a: %s\r\n",buf);
}
//7.close
close(fdw);
close(fdr);
return 0;
}//A
#include
//#include
#include
#include
#include
#include
#include
#define BUF_SIZE 20
int mian()
{
//1.mkfifoa可要可不要
int ret = -1;
ret = mkfifo("fifoa",0666);
if(ret < 0 && EEXIST != errno)
{
return -1;
}
printf("create fifoa ok!---\r\n");
//2.mkfifob可要可不要
ret = mkfifo("fifob",0666);
if(ret < 0 && EEXIST != errno)
{
return -1;
}
printf("create fifob ok!---\r\n");
//3.open fifoa
int fdr = open("fifoa",O_WRONLY,0666);
if(-1 == fdr)
{
return -1;
}
printf("3:open fifoa ok!--------\r\n");
//4.open fifob
int fdw = open("fifob",O_RDONLY,0666);
if(-1 == fdw)
{
return -1;
}
printf("4:open fifob ok!--------\r\n");
char buf[BUF_SIZE] = {0};
while(1)
{
//5.read
memset(buf,0,BUF_SIZE);
read(fdr,buf,BUF_SIZE);
printf("a->b: %s\r\n",buf);
//6.write
memset(buf,0,BUF_SIZE);
fgets(buf,BUF_SIZE,stdin);//get(buf);
write(fdw,buf,BUF_SIZE);
}
//7.close
close(fdw);
close(fdr);
return 0;
}//B
特点:
1.有名管道可以用于任意两个进程间的通信
2.有名管道可以实现双工通信(需要两个管道文件)
3.有名管道中的数据存放在内存中,管道中的数据读走后就不存在了,有名管道文件在文件系统中可见,文件大小为0
异步通信:被通信方不知道什么时候跟它通信
同步通信:发送方发数据,接收方收数据,双方需要在很短的时间内完成数据交换,否则会造成一方阻塞。
信号:信号是对中断的模拟,信号通信是一种异步通信方式,是一个通知
中断:是指CPU在执行程序的工程中插入了另外一段程序的过程
信号:Linux操作系统预先定义好了64个信号
kill -l 查看当前系统提供的所有信号
kill -9 进程号:给内核发送SIGKILL信号,让内核杀死指定进程
用户进程对信号的响应方式:捕获信号、忽略信号、采用默认处理动作
#include
#include
int main()
{
alarm(2);
printf("hello\r\n");
pause();//挂起
printf("world\r\n");
return 0;
}
#include
#include
#include
void Func(int signo)
{
printf("into Func:signo = %d\r\n",signo);
}
int main()
{
signal(SIGALRM,Func);
alarm(2);
printf("hello\r\n");
while(1)
{
pause();
}
printf("world\r\n");
return 0;
}
signal(信号,自定义的信号对应的处理函数)--->用来改变一个信号对应的默认处理动作
分析:alarm singal使用过程 信号处理流程-->alarm——test.c
#include
#include
#include
void Func(int signo)
{
printf("into Func:signo = %d\r\n",signo);
}
int main()
{
signal(SIGALRM,Func);
alarm(2);
printf("hello\r\n");
pause();
printf("world\r\n");
return 0;
}
实现两个进程的异步通信:
A:收信号进程 :signal pause
B:发信号进程:kill()
int kill(pid_t pid,int sig)
pid:对方进程号
sig:发的信号
#include
#include
#include
#include
int main(int argc,char *argv[])
{
if(2 != argc || NULL == argv[1])
{
return -1;
}
int pid = atoi(argv[1]);
if(pid <= 0)
{
return -1;
}
kill(pid,SIGUSR1);
return 0;
}//发信号程序
#include
#include
#include
void SigFunc(int signo)
{
printf("signo =%d\r\n",signo);
if(SIGUAR1 == signo)
{
printf("sig user1---------\r\n");
printf("hello\r\n");
}
else
{
printf("sig user2---------\r\n");
printf("world\r\n");
}
}
int main()
{
printf("pid = %d\r\n",getpid());
signal(SIGUSR1,SigFunc);
signal(SIGUSR2,SigFunc);
while(1)
{
pause();
}
}
A:1. ftok(".",int a)--->flag--->B进程通过该flag找到A进程
2. shmget
3. shmat
4. memcpy
B:1. ftok
2.shmget
3.shmat
4.printf()
key_t ftok(const char *pathname,int proj_id);
作用:生成对方进程找到自己的标识符
*pathname:用户指定的路径,可以是“.”,或“/home/farsight/.”
proj_id:0~255
返回值:成功 :产生一个key值;失败:-1
int shmget(key_t key,int size,int shmflg);
作用:创建一块共享内存
key:ftok的返回值或IPC_PRIVATE
size:共享内存大小
shmflg:操作共享内存的权限
返回值:成功shmID->标识创建成功的共享内存; 失败:-1
void *shmat(int shmid,const void *shmaddr,int shmflg);
作用:将本地内存和共享内存建立映射
shmid:共享内存的标识符,shmget 的返回值
*shmaddr:指向本地内存地址的指针,一般给NULL
shmflg:SHM_RDONLY-->共享内存只读
0-->共享内存可读写
返回值:指向映射成功后的本地内存地址
int shmdt(const void *shmaddr);
作用:取消映射
*shmaddr:映射成功后的本地内存地址,shmat的返回值
int shmctl(int shmid,int cmd,struct shmid_ds *buf);
作用:设置或获取共享内存属性
shmid:共享内存的标识符 shmget的返回值
cmd:操作选项IPC_STAT(获取对象属性)
IPC_SET(设置对象属性)
IPC_RMID(删除对象)
*buf:指向共享内存的属性值,IPC_STAT或IPC_SET时使用,IPC_RMID时该设置为NIULL
A:1. ftok
2. msgget
3. 创建消息结点
4. msgsnd
B:1. ftok
2. msgget
3.msgrcv
int msgget(ket_t key, int msgflg);
作用:创建一个消息队列
key : ftok的返回值
msgflg:IPC_CREAT|访问权限
返回值:成功 :消息队列ID;失败:-1
消息节点:一般有消息类型和消息正文组成
struct msgbuf
{
long m_type;//消息类型
char buf[BUF_SIZE];//消息正文,BUF_SIZE为消息大小
}
int masgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg);
作用:给消息队列发消息
msqid:消息队列ID
msgsz:消息的大小
msgflg:IPC_NOWAIT 消息没有发送完成函数也会立即返回。
0:直到发送完成函数才返回
返回值:0:成功;-1:失败
ssize_t msgrcv(int msqid,void *msgp,size_t msgsz,long msgtyp,int msgflg);
作用:从消息列队中读消息
msqid:消息队列ID
msgp:指向存放消息的结构体
msgsz:消息的大小
msgtyp:0:接收消息队列中的第一个消息
>0:按照消息类型接收消息(若同类型的消息有多个,先进先出原则接收)
Linux系统提供了三种信号灯:
1.无名信号灯----> sem_t sema---->用于线程间同步
2.有名信号灯---->sem_open ---->用于线程间同步
3.信号灯集----->多个信号灯的集合---->用于多个进程或线程间的同步
有名信号灯:
sem_t *sem_open(const char *name,int oflag,mode_t mode,unsigned int value);
作用:创建有名信号灯
*name:信号灯的名称
oflag:动作控制参数O_CREAT O_EXCL
mode:权限
value:信号灯的初值
返回值:指向创建成功的信号灯
#include
#include
#include
#include
#include
int main()
{
//1.create sem
sem_t *pSemA = sem_open("aaa",O_CREAT,0666,1);
if(SEM_FAILED == pSenA)
{
return -1;
}
printf("1:pSemA ok!------\r\n");
sem_t *pSemB = sem_open("bbb",O_CREAT,0666,0);
if(SEM_FAILED == pSemB)
{
return -1;
}
printf("2:pSemB ok!-------\r\n");
while(1)
{
sem_wait(pSemA);
printf("hello\r\n");
sleep(1);
sem_post(pSemB);
}
}
#include
#include
#include
#include
#include
int main()
{
//1.create sem
sem_t *pSemA = sem_open("aaa",O_CREAT,0666,1);
if(SEM_FAILED == pSenA)
{
return -1;
}
printf("1:pSemA ok!------\r\n");
sem_t *pSemB = sem_open("bbb",O_CREAT,0666,0);
if(SEM_FAILED == pSemB)
{
return -1;
}
printf("2:pSemB ok!-------\r\n");
while(1)
{
sem_wait(pSemB);
printf("world\r\n");
sleep(1);
sem_post(pSemA);
}
}