Linux 进程间通信例程
作者:互联网
1、pipe
1)只能用于具有亲缘关系的进程间通信
2)半双工通信,具有相同的读写端
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int pfd[2];
int pid;
int data = 23;
//create pipe
if(pipe(pfd) < 0)
{
//failed
perror(" create pipe failed !\n");
return -1;
}
else
{
if((pid = fork()) < 0)
{
perror("create process failed !\n");
}
else if(pid > 0)
{
//parent process
close(pfd[0]);
write(pfd[1],&data, sizeof(int));
close(pfd[1]);
}
else
{
//child process
close(pfd[1]);
read(pfd[0],&data,10);
close(pfd[0]);
}
}
}
内核实现步骤总结:
1. 初始化管道文件系统
2. 注册和加载文件系统
3. 建立write,read管道,返回文件以及文件描述符
4. 写和读
5. close
======================
do_pipe_flag
create_write_pipe
get_pipe_info
alloc_pipe_info
create_read_pipe
get_unused)fd_flags
fd_install
======================
2、fifo
mkfifo(const char *pathname,mode_t mode);
read例程:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define FIFO_PATH "my_fifo_file"
//read fifo
int main(void)
{
int fd;
char cont[255];
//create fifo file
if(mkfifo(FIFO_PATH,0666) < 0 && error != EEXIST)
{
perror("create fifo failed !\n");
return -1;
}
else
{
printf("create fifo success !\n");
//open file
fd = open(FIFO_PATH,O_CREATE|O_RDONLY,0666);
if(fd >0)
{
//read cont
while(1)
{
read(fd,cont,255);
printf("read : %s !\n",cont);
}
close(fd);
}
else
{
perror("open failed !\n");
}
return 0;
}
}
write例程:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define FIFO_PATH "my_fifo_file"
//read fifo
int main(void)
{
int fd;
char cont[] = " hello test";
//create fifo file
if(mkfifo(FIFO_PATH,0666) < 0 && error != EEXIST)
{
perror("create fifo failed !\n");
return -1;
}
else
{
printf("create fifo success !\n");
//open file
fd = open(FIFO_PATH,O_CREATE|O_RDONLY,0666);
if(fd >0)
{
//read cont
while(1)
{
write(fd,cont,strlen(cont));
printf("write success !\n");
}
close(fd);
}
else
{
perror("open failed !\n");
}
return 0;
}
}
3、 siginal
1. 软中断信号:用来通知进程发生了异步事件。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。
2. 信号只是用来通知进程发生了什么事件,并不给该进程传递任何数据。
//发送信号
1)想进程本身发送信号
int raise(int SIGNO);
2)向指定进程发送信号
int kill(pid_t pid,int SIGNO)
3) 特殊发送信号函数,比如:
unsigned int alarm(unsigned int seconds);
4) 等待信号
pause()
5) 内核代码跟踪
do_tkill
do_sned_soecific
do_send_sig_info
send_signal
__send_signal
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum,sighandler_t handler);
/********************************/
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
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("waiting for signal !\n");
//register signal
signal(SIGINT,sig_handler);
signal(SIGQUIT,sig_handler);
pause();
}
4、共享内存
write例程:
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
void *shm_addr;
int shmid;
char cont[] = "hello test";
//1. create share memory
shmid = shmget(12345,2048,IPC_CREATE|0666);
if(shmid != -1)
{
//2. map address
shm_addr = shmat(shmid,NULL,0);
if(share_memory != (void *)-1)
{
//copy mem
memcpy(shm_addr,cont,sizeof(cont));
printf("save success !\n");
shmdt(shm_addr);
}
else
{
perror("shmat:");
}
}
else
{
perror("shmget");
}
return 0;
}
read例程:
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
void *shm_addr;
int shmid;
char cont[] = "hello test";
//1. create share memory
shmid = shmget(12345,2048,IPC_CREATE|0666);
if(shmid != -1)
{
//2. map address
shm_addr = shmat(shmid,NULL,0);
if(share_memory != (void *)-1)
{
printf("get data = %s !\n",(char *)shm_addr);
shmdt(shm_addr);
}
else
{
perror("shmat:");
}
}
else
{
perror("shmget");
}
return 0;
}
5 消息队列
1、数据读一遍数据之后,数据就不存在了(消息被取走之后就不存在了)
2、默认的配置会导致阻塞,可以在recv 和snd 函数中设置NOWAIT
send例程:
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
struct magbuf
{
long mtype;
char ntext[255];
};
int main()
{
struct msgbuf mybuf;
int msggid = 0;
mybuf.mtype = 1;
strcpy(mybuf.ntext,"hello test");
//1. create message queue
msggid = msgget(2345,IPC_CREATE|0666);
if(msggid == -1)
{
//2. send message queue
if(msgsnd(msggid,&mybuf,sizeof(mybuf.ntext),0)!= -1)
{
printf("sned message success !\n");
}
else
{
perror(" send error !\n");
}
}
else
{
perror("msgget error !\n");
}
return 0;
}
recv例程:
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
struct magbuf
{
long mtype;
char ntext[255];
};
int main()
{
struct msgbuf mybuf;
int msggid = 0;
//1. create message queue
msggid = msgget(2345,IPC_CREATE|0666);
if(msggid == -1)
{
//2. send message queue
if(msgrecv(msggid,&mybuf,sizeof(mybuf.ntext),1,0)!= -1)
{
printf("recv message success ; %s !\n",mybuf.ntext);
//3. delete queue
if(msgctl(msggid,IPC_RMID,0) != -1)
{
printf(" delete queeu success !\n");
}
}
else
{
perror(" recv error !\n");
}
}
else
{
perror("msgget error !\n");
}
return 0;
}
6、信号量 semphore
操作流程:
1. 建立信号量
2. 操作信号量
3. lock unlock
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
int semid = 0;
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()
{
//1. create sem
semid = semget(2345.1,IPC_CREATE|0666);
if(semid != -1)
{
//2. set semaphore = 1
semctl(semid,1,SETVAL);
//3. locl unlock
down(); // lock
printf(" hello test !\n");
up(); // unlock
}
else
{
perror("semget error !\n");
}
return 0;
}
7、
7) socket
//socket 常用函数
socket -- create an endpoint for communication
int socket(int domain,int type,int protocol);
bind -- bind a name to a socket
int bind(int sockfd,const struct sockaddr *addr, socklen_t addrlen);
listen -- listen for connections on a socket
int listen(int sockfd,int backlog);
accept -- accept a connections on a socket
int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);
read ,write ,close
send,sendto ,sendmsg -- send a message to a socket
ssize_t send(int sockfd,const coid *buf,size_t len,int flags);
ssize_t snedto(int sockfd,const void *buf,size_t len,int flags,const struct sockaddr *dest_addr,socklen_t addrlen);
ssize_t sendmsg(int sockfd,const struct msghdr *msg,int flags);
recv,recvfrom,recvmsg -- receive a message from a socket
server例程:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
//server.c
int main()
{
int server_fd;
int client_fd;
struct sockaddr_un myaddr;
struct sockaddr_un client_addr;
myaddr.sun_family = AF_UNIX;
strcpy(myaddr.sun_path,"testsockfile");
int client_addr_len = sizeof(client_addr);
//1.socket
server_fd = socket(AF_UNIX,SOCK_STREAM,0);
if(serverfd == -1)
{
printf("socket error !\n");
exit(1);
}
// 2.bind
if(bind(serverfd,(struct sockaddr *)&myaddr,sizeof(myaddr)) == -1)
{
perror("bind error !\n");
exit(1);
}
// 3. listen
if(listen(server_fd,20 ) == -1) // 20 times
{
perror("listen error !\n");
exit(1);
}
// 4. accept
client_fd = accept(server_fd,(struct sockaddr *)&client_addr,&client_addr_len);
if(client_fd == -1)
{
perror("accept error !\n");
exit(1);
}
// 5. op
write(client_fd,"hello test",10);
// 6. close
close(client_fd);
close(server_fd);
return 0;
}
client例程:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
//client.c
int main()
{
int server_fd;
int client_fd;
char buf[100];
struct sockaddr_un myaddr;
struct sockaddr_un client_addr;
myaddr.sun_family = AF_UNIX;
strcpy(myaddr.sun_path,"testsockfile");
int client_addr_len = sizeof(client_addr);
//1.socket
server_fd = socket(AF_UNIX,SOCK_STREAM,0);
if(serverfd == -1)
{
printf("socket error !\n");
exit(1);
}
//2.connect
if(connect(serverfd,(struct sockaddr *)&myaddr,sizeof(myaddr)) == -1)
{
perror("connect error !\n");
exit(1);
}
// 3. op
read(serverfd,buf,100);
printf(" get server data = %s !\n",buf);
// 6. close
close(server_fd);
return 0;
}
标签:perror,addr,例程,间通信,int,fd,Linux,include,struct 来源: https://blog.csdn.net/jansert/article/details/122158803