1、 无名管道
代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <errno.h> #include <math.h> int main(int argc, char *argv[]) { pid_t pid; int pipe_fd[2]; char buf_r[100]; char *p_wbuf; int r_num; memset(buf_r, 0, sizeof(buf_r)); if(pipe(pipe_fd) < 0) { printf("pipe create error\n"); return -1; } //create child process if((pid = fork()) == 0) { printf("\n"); close(pipe_fd[1]); sleep(2); if((r_num = read(pipe_fd[0], buf_r, 100)) > 0) printf("%d numbers read from the pipe is %s\n", r_num, buf_r); close(pipe_fd[0]); exit(0); } else if(pid > 0) { close(pipe_fd[0]); if(write(pipe_fd[1], "Hello", 5) != -1) printf("parent write1 Hello\n"); if(write(pipe_fd[1], "Pipe", 5) != -1) printf("parent write2 Pipe\n"); close(pipe_fd[1]); waitpid(pid, NULL, 0); exit(0); } return 0; }
Makefile:
CC = gcc CURTDIR = $(shell pwd) TARGET = mypipe %.o:%.c $(CC)-c $(EXTRAFLAGS) $< -o $@ %.o:%.S $(CC)-c $(EXTRAFLAGS) $< -o $@ .PHONY: all clean $(TARGET): $(TARGET).o $(CC) -o $@ $^ clean: rm-rf $(TARGET) $(TARGET).o
运行结果:
eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.1$make gcc -c mypipe.c -o mypipe.o gcc -o mypipe mypipe.o eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.1$ls Makefile mypipe mypipe.c mypipe.o eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.1$./mypipe parent write1 Hello parent write2 Pipe 10 numbers read from the pipe is HelloPipe
结论:由于fork函数让子进程完整地拷贝了父进程的整个地址空间,所以父子进程都有管道的读端和写端。而我们需要的是一个进程读,一个进程写,所以写的进程最好关闭读端,读的进程关闭写端。
2、 有名管道
代码1:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <errno.h> #include <math.h> #define FIFO_SERVER "/tmp/myfifo" int main(int argc, char *argv[]) { int fd; char w_buf[100]; int nwrite; if((mkfifo(FIFO_SERVER, O_CREAT | O_EXCL | O_RDWR) < 0) && (errno!= EEXIST)) printf("cannot create fifoserver\n"); fd = open(FIFO_SERVER, O_RDWR | O_NONBLOCK, 0); if(fd == -1) { perror("open"); exit(1); } if(argc == 1) { printf("please send something\n"); exit(-1); } strcpy(w_buf, argv[1]); if((nwrite == write(fd, w_buf, 100)) == -1) { if(errno == EAGAIN) printf("The FIFO has not been read yet. please try later\n"); } else printf("write %s to the FIFO\n", w_buf); close(fd); return 0; }
代码2:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <errno.h> #include <math.h> #define FIFO_SERVER "/tmp/myfifo" int main(int argc, char *argv[]) { int fd; char buf_r[100]; int nread; if((mkfifo(FIFO_SERVER, O_CREAT | O_EXCL | O_RDWR) < 0) && (errno!= EEXIST)) printf("cannot create fifoserver\n"); fd = open(FIFO_SERVER, O_RDWR | O_NONBLOCK, 0); if(fd == -1) { perror("open"); exit(1); } while(1) { memset(buf_r, 0, sizeof(buf_r)); if(nread = read(fd, buf_r, 100) == -1) { if(errno == EAGAIN) printf("no datayet\n"); } printf("read %s from FIFO\n", buf_r); sleep(1); } close(fd); pause(); unlink(FIFO_SERVER); return 0; }
Makefile:
CC = gcc CURTDIR = $(shell pwd) TARGET = myfifo_write #TARGET = myfifo_read %.o:%.c $(CC)-c $(EXTRAFLAGS) $< -o $@ %.o:%.S $(CC)-c $(EXTRAFLAGS) $< -o $@ .PHONY: all clean $(TARGET): $(TARGET).o $(CC) -o $@ $^ clean: rm-rf $(TARGET) $(TARGET).o rm-rf $(TARGETR) $(TARGETR).o
运行结果:
eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.2$sudo ./myfifo_write hello write hello to the FIFO eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.2$sudo ./myfifo_write fifo write fifo to the FIFO eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.2$sudo ./myfifo_read no data yet read from FIFO no data yet read from FIFO no data yet read from FIFO read hello from FIFO no data yet read from FIFO read fifo from FIFO no data yet read from FIFO
总结:先创建一个有名管道,打开管道之后向管道中写入由主函数传入的字符串,然后另一个进程循环从管道中读取数据。当没有数据时,是读不到的,当有数据时,就可以读到了。
3、 信号处理
代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <errno.h> #include <math.h> #include <signal.h> void my_func(int sign_no) { if(sign_no == SIGBUS) { printf("I have get SIGBUS\n"); } } int main(int argc, char *argv[]) { printf("Waiting for signal SIGBUS\n"); signal(SIGBUS, my_func); pause(); return 0; }
Makefile:
CC = gcc CURTDIR = $(shell pwd) TARGET = mysig %.o:%.c $(CC)-c $(EXTRAFLAGS) $< -o $@ %.o:%.S $(CC)-c $(EXTRAFLAGS) $< -o $@ .PHONY: all clean $(TARGET): $(TARGET).o $(CC) -o $@ $^ clean: rm-rf $(TARGET) $(TARGET).o
运行结果:
eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$make gcc -c mysig.c -o mysig.o gcc -o mysig mysig.o eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$ls Makefile mysig mysig.c mysig.o eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$./mysig Waiting for signal SIGBUS
eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$ps -aux | grep mysig Warning: bad ps syntax, perhaps a bogus'-'? See http://procps.sf.net/faq.html eastmoon 10270 0.0 0.4 9116 3124 pts/2 S+ 15:09 0:00 vi mysig.txt eastmoon 10295 0.0 0.0 1728 244 pts/3 S+ 15:10 0:00 ./mysig eastmoon 10300 0.0 0.1 5804 876 pts/4 S+ 15:11 0:00 grep --color=auto mysig eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$kill -BUS 10295 eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$./mysig Waiting for signal SIGBUS I have get SIGBUS
总结:signal系统调用为SIGBUS信号注册了信号处理函数,然后将进程挂起等待SIGBUS信号,当向该进程发送SIGBUS信号才会执行信号处理函数。
4、 共享内存
代码1:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ipc.h> #include <sys/shm.h> #include <unistd.h> #include <errno.h> #include <math.h> #include <signal.h> #include "shm_com.h" int main(int argc, char *argv[]) { int running = 1; void *shared_memory = (void*)0; struct shared_use_st *shared_stuff; int shmid; shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT); if(shmid == -1) { fprintf(stderr, "shmget failed\n"); exit(EXIT_FAILURE); } shared_memory = shmat(shmid, (void*)0, 0); if(shared_memory == (void*)-1) { fprintf(stderr, "shmmat failed\n"); exit(EXIT_FAILURE); } printf("Memory attached at %x\n", (int)shared_memory); shared_stuff = (struct shared_use_st *)shared_memory; shared_stuff->written_by_you = 0; while(running) { if(shared_stuff->written_by_you) { printf("You wrote: %s\n", shared_stuff->some_text); sleep(1); shared_stuff->written_by_you = 0; if(strncmp(shared_stuff->some_text, "end", 3) == 0) { running = 0; } } } if(shmdt(shared_memory) == -1) { fprintf(stderr, "shmmdt failed\n"); exit(EXIT_FAILURE); } return 0; }
代码2:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ipc.h> #include <sys/shm.h> #include <unistd.h> #include <errno.h> #include <math.h> #include <signal.h> #include "shm_com.h" int main(int argc, char *argv[]) { int running = 1; void *shared_memory = (void*)0; struct shared_use_st *shared_stuff; char buffer[BUFSIZ]; int shmid; shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT); if(shmid == -1) { fprintf(stderr, "shmget failed\n"); exit(EXIT_FAILURE); } shared_memory = shmat(shmid, (void*)0, 0); if(shared_memory == (void*)-1) { fprintf(stderr, "shmmat failed\n"); exit(EXIT_FAILURE); } printf("Memory attached at %x\n", (int)shared_memory); shared_stuff = (struct shared_use_st *)shared_memory; shared_stuff->written_by_you = 0; while(running) { while(shared_stuff->written_by_you) { sleep(1); printf("Waiting for client....\n"); } printf("Enter some text: "); fgets(buffer, BUFSIZ, stdin); strncpy(shared_stuff->some_text, buffer, TEXT_SZ); shared_stuff->written_by_you = 1; if(strncmp(buffer, "end", 3) == 0) { running = 0; } } if(shmdt(shared_memory) == -1) { fprintf(stderr, "shmmdt failed\n"); exit(EXIT_FAILURE); } return 0; }
代码3:
#define TEXT_SZ 2048 struct shared_use_st { int written_by_you; char some_text[TEXT_SZ]; };
Makefile:
CC = gcc CURTDIR = $(shell pwd) #TARGET = myshm1 TARGET = myshm2 %.o:%.c $(CC)-c $(EXTRAFLAGS) $< -o $@ %.o:%.S $(CC)-c $(EXTRAFLAGS) $< -o $@ .PHONY: all clean $(TARGET): $(TARGET).o $(CC) -o $@ $^ clean: rm-rf $(TARGET) $(TARGET).o
运行结果:
eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$make gcc -c myshm1.c -o myshm1.o gcc -o myshm1 myshm1.o eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$ls Makefile myshm1 myshm1.c myshm1.o myshm2.c shm_com.h eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$make gcc -c myshm2.c -o myshm2.o gcc -o myshm2 myshm2.o eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$ls Makefile myshm1 myshm1.c myshm1.o myshm2 myshm2.c myshm2.o shm_com.h eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$./myshm1 Memory attached at b78db000 eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$./myshm2 Memory attached at b7731000 Enter some text: my first share memory Waiting for client.... Waiting for client.... Enter some text: it's so good Waiting for client.... Waiting for client.... Enter some text: ok, now let's study otherthings. Waiting for client.... Waiting for client.... Enter some text: end eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$./myshm1 Memory attached at b78db000 You wrote: my first share memory You wrote: it's so good You wrote: ok, now let's study otherthings. You wrote: end
总结:用于通信的两个进程必须用同一块共享内存进行通信,所以shmget的第一个参数key必须是相同的。
5、 消息队列
代码1:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <errno.h> #include <math.h> #include <signal.h> #include <sys/ipc.h> #include <sys/msg.h> struct my_msg_st { long int my_msg_type; char some_text[BUFSIZ]; }; int main(int argc, char *argv[]) { int running = 1; int msgid; struct my_msg_st some_data; long int msg_to_receive = 0; msgid = msgget((key_t)2222, 0666 | IPC_CREAT); if(msgid == -1) { fprintf(stderr, "msgget failed with error: %d\n", errno); exit(EXIT_FAILURE); } while(running) { if(msgrcv(msgid, (void*)&some_data, BUFSIZ, msg_to_receive, 0) ==-1) { fprintf(stderr, "msgrcv failed with error: %d\n", errno); exit(EXIT_FAILURE); } printf("You wrote: %s\n", some_data.some_text); if(strncmp(some_data.some_text, "end", 3) == 0) { running = 0; } } if(msgctl(msgid, IPC_RMID, 0) == -1) { fprintf(stderr, "msgctl failed with error: %d\n", errno); exit(EXIT_FAILURE); } return 0; }
代码2:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <errno.h> #include <math.h> #include <signal.h> #include <sys/ipc.h> #include <sys/msg.h> struct my_msg_st { long int my_msg_type; char some_text[BUFSIZ]; }; int main(int argc, char *argv[]) { int running = 1; int msgid; struct my_msg_st some_data; char buffer[BUFSIZ]; msgid= msgget((key_t)2222, 0666 | IPC_CREAT); if(msgid == -1) { fprintf(stderr, "msgget failed with error: %d\n", errno); exit(EXIT_FAILURE); } while(running) { printf("Enter some text:"); fgets(buffer, BUFSIZ, stdin); some_data.my_msg_type = 1; strcpy(some_data.some_text, buffer); if(msgsnd(msgid, (void*)&some_data, BUFSIZ, 0) == -1) { fprintf(stderr, "msgsnd failed with error: %d\n", errno); exit(EXIT_FAILURE); } if(strncmp(some_data.some_text, "end", 3) == 0) { running = 0; } } return 0; }
Makefile:
CC = gcc CURTDIR = $(shell pwd) TARGET = mymsg1 #TARGET = mymsg2 %.o:%.c $(CC)-c $(EXTRAFLAGS) $< -o $@ %.o:%.S $(CC)-c $(EXTRAFLAGS) $< -o $@ .PHONY: all clean $(TARGET): $(TARGET).o $(CC) -o $@ $^ clean: rm-rf $(TARGET) $(TARGET).o
运行结果:
eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$make gcc -c mymsg1.c -o mymsg1.o gcc -o mymsg1 mymsg1.o eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$ls Makefile mymsg1 mymsg1.c mymsg1.o eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$make gcc -c mymsg2.c -o mymsg2.o gcc -o mymsg2 mymsg2.o eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$ls Makefile mymsg1 mymsg1.c mymsg1.o mymsg2 mymsg2.c mymsg2.o eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$./mymsg2 Enter some text:hello Enter some text:mymsg Enter some text:good-buy Enter some text:end eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$./mymsg1 You wrote: hello You wrote: mymsg You wrote: good-buy You wrote: end
总结:在没有运行msg2向消息队列中添加消息的时候,msg1会阻塞在msgrcv函数上,运行msg2后,每添加一条消息,msg1就读取一条,直到添加的消息为”end”,结束。