目录
一、进程认知
将一个静态程序文件(Program)追加到内存当中,让CPU逐条执行做出相应动作,动态的进程(Process动态变化的过程)。
二、进程间通信方式(IPC)
1、无名管道(PIPE)和有名管道(FIFO)
1)PIPE:无名字,不能用open()打开操作,半双工,只能用于亲缘进程间,对写操作不做任何保护,若多进程或多线程对其进行写操作,会造成数据践踏。
int pipe (int fildes[2]); //fd[0]读,fd[1]写
//pipe不能用lseek定位,像是看不见源的水龙头无法定位
2)FIFO:有名字,可以用opne()来进行文件描述符操作,支持多者同时写入,跟普通文件一样可以使用write()/read()来进行读写。
int mkfifo(const char *pathname, mode_t mode); //FIFO文件名,文件权限
//不能使用lseek()定位,原因同PIPE一样
2、信号(SIGNAL)
1)非实时信号:前面31个信号(1-31)
2)实时信号:后面31个信号(34-64)
//信号是异步性的,操作要谨慎
void (*signal (int __sig, void (*__handler)(int)))(int); //捕捉指定信号
int kill (pid_t, int); //进程发送指定信号
3、消息队列(MSG)
1)使用方法:
1-1)发送者(snd):获取消息队列的ID;将数据放入附带标识的特殊结构体里面,发送给消息队列;
1-2)接收者(rcv):获取消息队列ID;将指定标识的消息读出;
带消息标识的特殊管道通信方式,当snd,rcv不再使用消息队列时,及时删除释放系统资源;
int msgget (key_t __key, int __msgflg); //获取消息队列ID
key的获取ftok()
/* Template for struct to be used as argument for `msgsnd' and `msgrcv'. */
struct msgbuf
{
long int mtype; /* type of received/sent message 不能是0L*/
char mtext[1]; /* text of the message */
};
int msgsnd (int __msqid, __const void *__msgp, size_t __msgsz,
int __msgflg); //发送
ssize_t msgrcv (int __msqid, void *__msgp, size_t __msgsz,
long int __msgtyp, int __msgflg); //接收
/* Message queue control operation. */
int msgctl (int __msqid, int __cmd, struct msqid_ds *__buf); //设置或获取消息队列的相关属性
消息队列不适用于海量数据传输,因为数据需从用户态转折到内核态,效率不高;
4、共享内存(SHM)
1)使用方法
1-1)获取共享内存对象的ID;
1-2)将共享内存映射;
1-3)不再使用时解除映射关系;
1-4)没有进程使用共享内存时,删除。
int shmget (key_t __key, size_t __size, int __shmflg); //获取共享内存ID
//size = 1024 整数倍
/* Attach shared memory segment. 共享内存映射*/
void *shmat (int __shmid, __const void *__shmaddr, int __shmflg); //将shmaddr设置为NULL,简单移植性强
/* Detach shared memory segment. 解除映射*/
extern int shmdt (__const void *__shmaddr);
int shmctl (int __shmid, int __cmd, struct shmid_ds *__buf); //获取或设置共享内存的相关属性
进程间通信效率最高的方式,需结合信号量等同步互斥机制一起使用;
5、信号量(SEM)
见线程的信号量描述,作为进程之间以及同一进程的不同线程之间的同步和互斥手段;
6、socket套接字
//来自于zqixiao_09文章摘录
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 8888
#define MAXSIZE 128
int main()
{
int i,nbyte;
int listenfd, confd, maxfd;
char buffer[MAXSIZE];
fd_set global_rdfs, current_rdfs;
struct sockaddr_in addr,clientaddr;
int addrlen = sizeof(struct sockaddr_in);
int caddrlen = sizeof(struct sockaddr_in);
if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket error");
exit(-1);
}
else
{
printf("socket successfully!\n");
printf("listenfd : %d\n",listenfd);
}
memset(&addr, 0 ,addrlen);
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(listenfd,(struct sockaddr *)&addr,addrlen) == -1)
{
perror("bind error");
exit(-1);
}
else
{
printf("bind successfully!\n");
printf("listen port:%d\n",PORT);
}
if(listen(listenfd,5) == -1)
{
perror("listen error");
exit(-1);
}
else
{
printf("listening...\n");
}
maxfd = listenfd;
FD_ZERO(&global_rdfs);
FD_SET(listenfd,&global_rdfs);
while(1)
{
current_rdfs = global_rdfs;
if(select(maxfd + 1,¤t_rdfs, NULL, NULL,0) < 0)
{
perror("select error");
exit(-1);
}
for(i = 0; i <= listenfd + 1; i++)
{
if(FD_ISSET(i, ¤t_rdfs))
{
if(i == listenfd)
{
if((confd = accept(listenfd,(struct sockaddr *)&clientaddr,&caddrlen)) == -1)
{
perror("accept error");
exit(-1);
}
else
{
printf("Connect from [IP:%s PORT:%d]\n",
inet_ntoa(clientaddr.sin_addr),clientaddr.sin_port);
FD_SET(confd,&global_rdfs);
maxfd = (maxfd > confd ? maxfd : confd);
}
}
else
{
if((nbyte = recv(i, buffer, sizeof(buffer),0)) < 0)
{
perror("recv error");
exit(-1);
}
else if(nbyte == 0)
{
close(i);
FD_CLR(i,&global_rdfs);
}
else
{
printf("recv:%s\n",buffer);
send(i, buffer, sizeof(buffer),0);
}
}
}
}
}
return 0;
}
应用于不同主机之间的进程间通信。