├── ipc ├── select_poll │ ├── multiplexing │ │ ├── readme.txt │ │ └── multiplexing.c │ ├── select_demo │ │ ├── readme.txt │ │ └── select_demo.c │ ├── readme.txt │ └── select_detail │ │ └── select_detail.c ├── pipe │ ├── fifo │ │ ├── Makefile │ │ └── fifo.c │ ├── pipe_test │ │ ├── Makefile │ │ └── pipe_test.c │ └── pipe_shell │ │ ├── Makefile │ │ └── pipe_shell.c ├── semaphore │ ├── test1 │ │ ├── test1.o │ │ ├── Makefile │ │ └── test1.c │ ├── test2 │ │ ├── test2.o │ │ ├── Makefile │ │ └── test2.c │ ├── test3 │ │ ├── test3.o │ │ ├── Makefile │ │ └── test3.c │ ├── test4 │ │ ├── test4.o │ │ ├── Makefile │ │ └── test4.c │ └── os_semaphere │ │ ├── OS5.PPT │ │ ├── lab44.ppt │ │ ├── 111110305.doc │ │ ├── mutex │ │ ├── mutex.o │ │ ├── Makefile │ │ └── mutex.c │ │ └── 车辆死锁和管道通信实验报告.doc ├── ShareMemory │ ├── client │ │ ├── Makefile │ │ └── client.c │ └── server │ │ ├── Makefile │ │ └── server.c ├── queue │ ├── queue_lucy │ │ ├── Makefile │ │ └── queue_lucy.c │ ├── queue_peter │ │ ├── Makefile │ │ └── queue_peter.c │ └── cutter_customer │ │ ├── readme.txt │ │ ├── customer.c │ │ ├── cutter.c │ │ └── desk.c └── process │ └── waitpid.c └── README.md /ipc/select_poll/multiplexing/readme.txt: -------------------------------------------------------------------------------- 1 | 1.很好的实现了io复用或者说socket复用. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | linux_ipc 2 | ========= 3 | 4 | 关于linux ipc进程间通信自己的收录的一些代码 5 | -------------------------------------------------------------------------------- /ipc/pipe/fifo/Makefile: -------------------------------------------------------------------------------- 1 | 2 | #gcc fifo 3 | fifo:fifo.o 4 | gcc -o $@ $^ 5 | ..c.o: 6 | gcc -c $< 7 | -------------------------------------------------------------------------------- /ipc/semaphore/test1/test1.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnemoug/linux_ipc/HEAD/ipc/semaphore/test1/test1.o -------------------------------------------------------------------------------- /ipc/semaphore/test2/test2.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnemoug/linux_ipc/HEAD/ipc/semaphore/test2/test2.o -------------------------------------------------------------------------------- /ipc/semaphore/test3/test3.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnemoug/linux_ipc/HEAD/ipc/semaphore/test3/test3.o -------------------------------------------------------------------------------- /ipc/semaphore/test4/test4.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnemoug/linux_ipc/HEAD/ipc/semaphore/test4/test4.o -------------------------------------------------------------------------------- /ipc/semaphore/test1/Makefile: -------------------------------------------------------------------------------- 1 | 2 | #gcc test1 3 | test1:test1.o 4 | gcc -o $@ $^ 5 | ..c.o: 6 | gcc -c $< 7 | -------------------------------------------------------------------------------- /ipc/semaphore/test2/Makefile: -------------------------------------------------------------------------------- 1 | 2 | #gcc test2 3 | test2:test2.o 4 | gcc -o $@ $^ 5 | ..c.o: 6 | gcc -c $< 7 | -------------------------------------------------------------------------------- /ipc/semaphore/test3/Makefile: -------------------------------------------------------------------------------- 1 | 2 | #gcc test3 3 | test3:test3.o 4 | gcc -o $@ $^ 5 | ..c.o: 6 | gcc -c $< 7 | -------------------------------------------------------------------------------- /ipc/ShareMemory/client/Makefile: -------------------------------------------------------------------------------- 1 | 2 | #gcc client 3 | client:client.o 4 | gcc -o $@ $^ 5 | ..c.o: 6 | gcc -c $< 7 | -------------------------------------------------------------------------------- /ipc/ShareMemory/server/Makefile: -------------------------------------------------------------------------------- 1 | 2 | #gcc server 3 | server:server.o 4 | gcc -o $@ $^ 5 | ..c.o: 6 | gcc -c $< 7 | -------------------------------------------------------------------------------- /ipc/pipe/pipe_test/Makefile: -------------------------------------------------------------------------------- 1 | 2 | #gcc pipe_test 3 | pipe_test:pipe_test.o 4 | gcc -o $@ $^ 5 | ..c.o: 6 | gcc -c $< 7 | -------------------------------------------------------------------------------- /ipc/semaphore/os_semaphere/OS5.PPT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnemoug/linux_ipc/HEAD/ipc/semaphore/os_semaphere/OS5.PPT -------------------------------------------------------------------------------- /ipc/semaphore/test4/Makefile: -------------------------------------------------------------------------------- 1 | 2 | #gcc test4 3 | test4:test4.o 4 | gcc -o $@ $^ -pthread 5 | ..c.o: 6 | gcc -c $< 7 | -------------------------------------------------------------------------------- /ipc/pipe/pipe_shell/Makefile: -------------------------------------------------------------------------------- 1 | 2 | #gcc pipe_shell 3 | pipe_shell:pipe_shell.o 4 | gcc -o $@ $^ 5 | ..c.o: 6 | gcc -c $< 7 | -------------------------------------------------------------------------------- /ipc/queue/queue_lucy/Makefile: -------------------------------------------------------------------------------- 1 | 2 | #gcc queue_lucy 3 | queue_lucy:queue_lucy.o 4 | gcc -o $@ $^ 5 | ..c.o: 6 | gcc -c $< 7 | -------------------------------------------------------------------------------- /ipc/semaphore/os_semaphere/lab44.ppt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnemoug/linux_ipc/HEAD/ipc/semaphore/os_semaphere/lab44.ppt -------------------------------------------------------------------------------- /ipc/queue/queue_peter/Makefile: -------------------------------------------------------------------------------- 1 | 2 | #gcc queue_peter 3 | queue_peter:queue_peter.o 4 | gcc -o $@ $^ 5 | ..c.o: 6 | gcc -c $< 7 | -------------------------------------------------------------------------------- /ipc/semaphore/os_semaphere/111110305.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnemoug/linux_ipc/HEAD/ipc/semaphore/os_semaphere/111110305.doc -------------------------------------------------------------------------------- /ipc/semaphore/os_semaphere/mutex/mutex.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnemoug/linux_ipc/HEAD/ipc/semaphore/os_semaphere/mutex/mutex.o -------------------------------------------------------------------------------- /ipc/semaphore/os_semaphere/mutex/Makefile: -------------------------------------------------------------------------------- 1 | 2 | #gcc mutex 3 | mutex:mutex.o 4 | gcc -o $@ $^ -pthread 5 | ..c.o: 6 | gcc -c $< 7 | -------------------------------------------------------------------------------- /ipc/semaphore/os_semaphere/车辆死锁和管道通信实验报告.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnemoug/linux_ipc/HEAD/ipc/semaphore/os_semaphere/车辆死锁和管道通信实验报告.doc -------------------------------------------------------------------------------- /ipc/queue/cutter_customer/readme.txt: -------------------------------------------------------------------------------- 1 | 1.这是经典的理发师问题: 2 | 首先运行desk可执行文件,进行总的判断:无论理发师或顾客来都会发消息给他 3 | 这几个文件通过共同的约定msgtyp或msg.mtype来接受消息处理问题 4 | 他对消息队列用的一般,结构处理一般 5 | 6 | -------------------------------------------------------------------------------- /ipc/select_poll/select_demo/readme.txt: -------------------------------------------------------------------------------- 1 | 在linux下,当一个用户进程被创建的时候,系统会自动为该进程创建三个数据流:stdout,stdin,stderr,他们的中文名字分别是标准输出,标准输入,标准错误.他们是FIFO*类型,属于标准IO,在中。他们的值一般是1,0,2. 2 | 该程序的作用是检测该程序进程的标准输入流,当其有数据可读或者说想该进程的标准输入流写数据时,select会马上返回。 3 | 运行该程序应该:./select_demo 然后随意输入数据然后按Enter键. 4 | -------------------------------------------------------------------------------- /ipc/select_poll/readme.txt: -------------------------------------------------------------------------------- 1 | 1.select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchronous I/O multiplexing 2 | select() (or pselect()) is used to efficiently monitor multiple file descriptors, to see if any of them is, or becomes, "ready"; that is, to see whether I/O becomes possible, or an "exceptional condition" has occurred on any of the descriptors. 3 | 2. 4 | -------------------------------------------------------------------------------- /ipc/pipe/pipe_shell/pipe_shell.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char **argv) 7 | { 8 | FILE *finput, *foutput; //FILE表示是文件指针 9 | char buffer[PIPE_BUF]; 10 | int n; 11 | finput = popen("echo test!", "r"); //链接到finput的标准输入 12 | foutput = popen("cat", "w"); //链接到foutput的标准输出 13 | /*fileno()返回文件描述符,文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件*/ 14 | read(fileno(finput), buffer, strlen("test!")); 15 | printf("buffer read from finput is %s\n",buffer); 16 | write(fileno(foutput), buffer, strlen("test")); 17 | pclose(finput); 18 | pclose(foutput); 19 | printf("\n"); 20 | 21 | exit(EXIT_SUCCESS); 22 | } 23 | -------------------------------------------------------------------------------- /ipc/process/waitpid.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | int main() 6 | { 7 | pid_t pc,pr; 8 | pc=fork(); 9 | if (pc<0)/* fork错误*/ 10 | { 11 | printf("fork error\n"); 12 | exit(1); 13 | } 14 | else if(pc==0)/*在子进程中*/ 15 | { 16 | sleep(10); 17 | exit(0); 18 | } 19 | else 20 | { 21 | do {/* 使用了WNOHANG参数,waitpid不会在这里等待 */ 22 | pr=waitpid(pc,NULL,WNOHANG); 23 | if (pr==0) 24 | { 25 | printf("No child exit\n"); 26 | sleep(1); 27 | } 28 | }while (pr==0); 29 | if (pr==pc) 30 | printf("successfully get child %d\n",pr); 31 | else 32 | printf("wait child error\n"); 33 | } 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /ipc/select_poll/select_demo/select_demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int 8 | main(void) 9 | { 10 | fd_set rfds; 11 | struct timeval tv; 12 | int retval; 13 | 14 | /* Watch stdin (fd 0) to see when it has input. */ 15 | FD_ZERO(&rfds); 16 | FD_SET(0, &rfds); 17 | 18 | /* Wait up to five seconds. */ 19 | tv.tv_sec = 5; 20 | tv.tv_usec = 0; 21 | 22 | retval = select(1, &rfds, NULL, NULL, &tv); 23 | /* Don't rely on the value of tv now! */ 24 | 25 | if (retval == -1) 26 | perror("select()"); 27 | else if (retval) 28 | printf("Data is available now.\n"); 29 | /* FD_ISSET(0, &rfds) will be true. */ 30 | else 31 | printf("No data within five seconds.\n"); 32 | 33 | exit(EXIT_SUCCESS); 34 | } 35 | -------------------------------------------------------------------------------- /ipc/pipe/fifo/fifo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define FIFO "/tmp/my_fifo" 8 | //本程序从一个FIFO读数据,并把读到的数据打印到标准输出 9 | //如果读到字符“Q”,则退出 10 | int main(int argc, char** argv) 11 | { 12 | char buf_r[100]; 13 | int fd; 14 | int nread; 15 | if((mkfifo(FIFO, O_CREAT) < 0) && (errno != EEXIST)) //创建命名管道 16 | { 17 | printf("不能创建FIFO\n"); 18 | exit(1); 19 | } 20 | 21 | printf("准备读取数据\n"); 22 | fd = open(FIFO, O_RDONLY, 0); 23 | if(fd == -1) 24 | { 25 | perror("打开FIFO"); 26 | exit(1); 27 | } 28 | 29 | while(1) 30 | { 31 | if((nread = read(fd, buf_r, 100)) == -1) 32 | { 33 | if(errno == EAGAIN) 34 | printf("没有数据\n"); 35 | } 36 | 37 | //假设取到Q的时候退出 38 | if(buf_r[0]=='Q') 39 | break; 40 | buf_r[nread]=0; 41 | printf("从FIFO读取的数据为:%s\n", buf_r); 42 | sleep(1); 43 | } 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /ipc/pipe/pipe_test/pipe_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main() 9 | { 10 | int pipe_fd[2]; 11 | pid_t pid; 12 | char buf_r[100]; 13 | char* p_wbuf; 14 | int r_num; 15 | memset(buf_r,0,sizeof(buf_r)); 16 | if(pipe(pipe_fd)<0) 17 | { 18 | printf("pipe create error\n"); 19 | return -1; 20 | } 21 | if((pid=fork())==0) 22 | { 23 | printf("\n"); 24 | close(pipe_fd[1]); 25 | sleep(2); 26 | if((r_num=read(pipe_fd[0],buf_r,100))>0) 27 | { 28 | printf( "%d numbers read from the pipe is %s\n",r_num,buf_r); 29 | } 30 | close(pipe_fd[0]); 31 | exit(0); 32 | } 33 | else if(pid>0) 34 | { 35 | close(pipe_fd[0]); 36 | if(write(pipe_fd[1],"Hello",5)!=-1) 37 | printf("parent write1 success!\n"); 38 | if(write(pipe_fd[1]," Pipe",5)!=-1) 39 | printf("parent write2 success!\n"); 40 | close(pipe_fd[1]); 41 | sleep(3); 42 | waitpid(pid,NULL,0); 43 | exit(0); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ipc/queue/queue_peter/queue_peter.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define PROJID 0xFF 12 | #define LUCY 1 13 | #define PETER 2 14 | 15 | int main() 16 | { 17 | char filenm[] = "queue_lucy.c"; 18 | int mqid; 19 | key_t mqkey; 20 | struct msgbuf 21 | { 22 | long mtype; /* message type, must be > 0 */ 23 | char mtext[256]; /* message data */ 24 | }msg; 25 | int ret; 26 | 27 | mqkey = ftok(filenm, PROJID); 28 | if(mqkey == -1) 29 | { 30 | perror("ftok error: "); 31 | exit(-1); 32 | } 33 | 34 | mqid = msgget(mqkey, 0); 35 | if(mqid == -1) 36 | { 37 | perror("msgget error: "); 38 | exit(-1); 39 | } 40 | 41 | while(1) 42 | { 43 | msgrcv(mqid,&msg,256,LUCY,0); 44 | printf("Lucy: %s\n",msg.mtext); 45 | printf("Peter: "); 46 | fgets(msg.mtext,256,stdin); 47 | if(strncmp("quit", msg.mtext, 4) == 0) 48 | { 49 | exit(0); 50 | } 51 | msg.mtext[strlen(msg.mtext)-1] = '\0'; 52 | msg.mtype = PETER; 53 | msgsnd(mqid,&msg,strlen(msg.mtext) + 1,0); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ipc/semaphore/test1/test1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void main() 8 | { 9 | key_t unique_key; /* 定义一个IPC关键字*/ 10 | int id; 11 | struct sembuf lock_it; 12 | int i; 13 | 14 | union semun{ 15 | int val; 16 | struct semid_ds *buf; 17 | unsigned short *array; 18 | }options; 19 | 20 | unique_key = ftok(".", 'a'); /* 生成关键字,字符'a'是一个随机种子*/ 21 | /* 创建一个新的信号量集合*/ 22 | id = semget(unique_key, 1, IPC_CREAT | IPC_EXCL | 0666); //用于判断是否存在此信号量,若存在错误退出 23 | printf("semaphore id=%d\n", id); 24 | options.val = 1; /*设置变量值*/ 25 | semctl(id, 0,SETVAL,options); /*设置索引0的信号量*/ 26 | 27 | /*打印出信号量的值*/ 28 | i = semctl(id, 0, GETVAL, 0); //返回信号量的值 29 | printf("value of semaphore at index 0 is %d\n", i); 30 | 31 | /*下面重新设置信号量*/ 32 | lock_it.sem_num = 0; /*设置哪个信号量*/ 33 | lock_it.sem_op = -1; /*定义操作*/ 34 | lock_it.sem_flg = IPC_NOWAIT; /*操作方式*/ 35 | if (semop(id, &lock_it, 1) == -1) //p(),申请资源 36 | { 37 | printf("can not lock semaphore.\n"); 38 | exit(1); 39 | } 40 | 41 | i = semctl(id, 0, GETVAL, 0); 42 | printf("value of semaphore at index 0 is %d\n", i); 43 | 44 | /*清除信号量*/ 45 | semctl(id, 0, IPC_RMID, 0); 46 | } 47 | -------------------------------------------------------------------------------- /ipc/queue/queue_lucy/queue_lucy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define PROJID 0xFF 12 | #define LUCY 1 13 | #define PETER 2 14 | 15 | int mqid; 16 | 17 | void terminate_handler(int signo) 18 | { 19 | msgctl(mqid,IPC_RMID,NULL); //用于处理消息队列 20 | exit(0); 21 | } 22 | 23 | int main() 24 | { 25 | char filenm[] = "queue_lucy.c"; 26 | key_t mqkey; 27 | struct msgbuf // 28 | { 29 | long mtype; /* message type, must be > 0 */ 30 | char mtext[256]; /* message data */ 31 | }msg; 32 | int ret; 33 | 34 | mqkey = ftok(filenm,PROJID); 35 | if(mqkey == -1) 36 | { 37 | perror("ftok error: "); 38 | exit(-1); 39 | } 40 | 41 | mqid = msgget(mqkey,IPC_CREAT | IPC_EXCL | 0666); //初始化消息队列 42 | if(mqid == -1) 43 | { 44 | perror("msgget error: "); 45 | exit(-1); 46 | } 47 | 48 | signal(SIGINT, terminate_handler); //处理ctrl+c信号 49 | signal(SIGTERM, terminate_handler); //kill命令信号 50 | 51 | while(1) 52 | { 53 | printf("Lucy: "); 54 | fgets(msg.mtext, 256, stdin); //从标准输入流输入数据 55 | if (strncmp("quit", msg.mtext, 4) == 0) 56 | { 57 | msgctl(mqid,IPC_RMID,NULL); 58 | exit(0); 59 | } 60 | msg.mtext[strlen(msg.mtext)-1] = '\0'; 61 | msg.mtype = LUCY; 62 | msgsnd(mqid,&msg,strlen(msg.mtext) + 1,0); 63 | msgrcv(mqid,&msg,256,PETER,0); //若不存在则阻塞 64 | printf("Peter: %s\n", msg.mtext); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /ipc/ShareMemory/client/client.c: -------------------------------------------------------------------------------- 1 | /*client.c:从共享内存中读出People*/ 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int semid; 8 | int shmid; 9 | 10 | /*信号量的P操作*/ 11 | void p() 12 | { 13 | struct sembuf sem_p; 14 | sem_p.sem_num=0; 15 | sem_p.sem_op=-1; 16 | if(semop(semid,&sem_p,1)==-1) 17 | printf("p operation is fail\n"); 18 | } 19 | 20 | /*信号量的V操作*/ 21 | void v() 22 | { 23 | struct sembuf sem_v; 24 | sem_v.sem_num=0; 25 | sem_v.sem_op=1; 26 | if(semop(semid,&sem_v,1)==-1) 27 | printf("v operation is fail\n"); 28 | } 29 | 30 | int main() 31 | { 32 | key_t semkey; 33 | key_t shmkey; 34 | semkey=ftok("../test/client/VenusDB.cbp",0); 35 | shmkey=ftok("../test/client/main.c",0); 36 | 37 | struct People{ 38 | char name[10]; 39 | int age; 40 | }; 41 | 42 | /*读取共享内存和信号量的IPC*/ 43 | semid=semget(semkey,0,0666); 44 | if(semid==-1) 45 | printf("creat sem is fail\n"); 46 | shmid=shmget(shmkey,0,0666); 47 | if(shmid==-1) 48 | printf("creat shm is fail\n"); 49 | 50 | /*将共享内存映射到当前进程的地址中,之后直接对进程中的地址addr操作就是对共享内存操作*/ 51 | struct People *addr; 52 | addr=(struct People*)shmat(shmid,0,0); 53 | if(addr==(struct People*)-1) 54 | printf("shm shmat is fail\n"); 55 | 56 | /*从共享内存读出数据*/ 57 | p(); 58 | printf("name:%s\n",addr->name); 59 | printf("age:%d\n",addr->age); 60 | v(); 61 | 62 | /*将共享内存与当前进程断开*/ 63 | if(shmdt(addr)==-1) 64 | printf("shmdt is fail\n"); 65 | 66 | /*IPC必须显示删除。否则会一直留存在系统中*/ 67 | if(semctl(semid,0,IPC_RMID,0)==-1) 68 | printf("semctl delete error\n"); 69 | if(shmctl(shmid,IPC_RMID,NULL)==-1) 70 | printf("shmctl delete error\n"); 71 | } 72 | -------------------------------------------------------------------------------- /ipc/semaphore/test4/test4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include /* For O_* constants */ 6 | #include /* For mode constants */ 7 | #include 8 | 9 | #define SHM_KEY 0x33 10 | 11 | int main(int argc, char **argv) 12 | { 13 | pid_t pid; 14 | int i, shmid; 15 | int *ptr; 16 | sem_t *sem; 17 | 18 | /* 创建一块共享内存, 存一个int变量 */ 19 | if ((shmid = shmget(SHM_KEY, sizeof(int), IPC_CREAT | 0600)) == -1) { 20 | perror("msgget"); 21 | } 22 | 23 | /* 将共享内存映射到进程, fork后子进程可以继承映射 */ 24 | if ((ptr = (int *)shmat(shmid, NULL, 0)) == (void *)-1) { 25 | perror("shmat"); 26 | } 27 | *ptr = 0; 28 | 29 | /* posix的有名信号量是kernel persistent的 30 | * 调用sem_unlink删除以前的信号量 */ 31 | sem_unlink("/mysem"); 32 | 33 | /* 创建新的信号量, 初值为1, sem_open会创建共享内存 34 | * 所以信号量是内核持续的 */ 35 | if ((sem = sem_open("/mysem", O_CREAT, 0600, 1)) == SEM_FAILED) { 36 | perror("sem_open"); 37 | } 38 | 39 | if ((pid = fork()) < 0) { 40 | perror("fork"); 41 | } else if (pid == 0) { /* Child */ 42 | /* 子进程对共享内存加1 */ 43 | for (i = 0; i < 100; i++) { 44 | sem_wait(sem); 45 | (*ptr)++; 46 | sem_post(sem); 47 | printf("child: %d\n", *ptr); 48 | } 49 | } else { /* Parent */ 50 | /* 父进程对共享内存减1 */ 51 | for (i = 0; i < 100; i++) { 52 | sem_wait(sem); 53 | (*ptr)--; 54 | sem_post(sem); 55 | printf("parent: %d\n", *ptr); 56 | } 57 | waitpid(pid); 58 | /* 如果同步成功, 共享内存的值为0 */ 59 | printf("finally: %d\n", *ptr); 60 | sem_unlink("/mysem"); 61 | } 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /ipc/queue/cutter_customer/customer.c: -------------------------------------------------------------------------------- 1 | //顾客进程 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define MSGKEY 66 8 | #define MONKEY 88 9 | enum{CUTTER,CUSTOMERIN,CUSTOMERLEAVE,ROOM,SEAT,WORK,FULL,CHARGE,END,OK}; 10 | int my_pid; 11 | int get_pid; 12 | int state; 13 | int my_index; 14 | int get_index; 15 | int msgid; 16 | int monid; 17 | int cutter; 18 | int cutterindex; 19 | int customer; 20 | int customerindex; 21 | char *name; 22 | struct msgform{ 23 | long mtype; 24 | char mtext[40]; 25 | }msg; 26 | union senum{ 27 | int val; 28 | }sen; 29 | void msgsend(int des,int state,int index) 30 | { 31 | msg.mtype=des; 32 | int *temp=(int*)msg.mtext; 33 | temp[0]=my_pid; 34 | temp[1]=state; 35 | temp[2]=index; 36 | msgsnd(msgid,&msg,sizeof(int)*3,0); 37 | } 38 | void msgreceive(int des) 39 | { 40 | msgrcv(msgid,&msg,sizeof(int)*3,des,0); 41 | int *temp=(int*)msg.mtext; 42 | get_pid=temp[0]; 43 | state=temp[1]; 44 | get_index=temp[2]; 45 | } 46 | void call_seat() 47 | { 48 | printf("找到一个理发店,我的编号是%d\n",get_index); 49 | if(state==ROOM) 50 | { 51 | printf("我来到大厅等候\n"); 52 | msgsend(3,ROOM,my_index); 53 | msgreceive(my_pid); 54 | } 55 | if(state==SEAT) 56 | { 57 | printf("我来到座位上等候\n"); 58 | msgsend(2,SEAT,my_index); 59 | msgreceive(my_pid); 60 | } 61 | if(state==WORK) 62 | { 63 | msgsend(4,WORK,my_index); 64 | msgreceive(my_pid); 65 | printf("编号为%d的理发师为我理发...\n",get_index); 66 | msgreceive(my_pid); 67 | printf("理发完毕,正在找钱...\n"); 68 | msgsend(1,CUSTOMERLEAVE,my_index); 69 | msgreceive(my_pid); 70 | printf("找钱完毕,离开...\n"); 71 | } 72 | } 73 | main(int argc,char *argv[]) 74 | { 75 | name=(argv[1]==NULL)?"\0":argv[1]; 76 | msgid=msgget(MSGKEY,0666|IPC_CREAT); 77 | my_pid=getpid(); 78 | printf("我是%s我正在寻找理发店理发\n",name); 79 | msgsend(1,CUSTOMERIN,0); 80 | msgreceive(my_pid); 81 | my_index=get_index; 82 | if(state==FULL) 83 | printf("理发店人满,离开...\n"); 84 | else 85 | call_seat(); 86 | } 87 | -------------------------------------------------------------------------------- /ipc/queue/cutter_customer/cutter.c: -------------------------------------------------------------------------------- 1 | //理发师进程 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define MSGKEY 66 8 | #define MONKEY 88 9 | enum{CUTTER,CUSTOMERIN,CUSTOMERLEAVE,ROOM,SEAT,WORK,FULL,CHARGE,END,OK}; 10 | int my_pid; 11 | int get_pid; 12 | int state; 13 | int my_index; 14 | int get_index; 15 | int msgid; 16 | int monid; 17 | int cutter; 18 | int cutterindex; 19 | int customer; 20 | int customerindex; 21 | char *name; 22 | struct msgform{ 23 | long mtype; 24 | char mtext[40]; 25 | }msg; 26 | struct sembuf P,V; 27 | union senum{ 28 | int val; 29 | }sen; 30 | void msgsend(int des,int state,int index) 31 | { 32 | msg.mtype=des; 33 | int *temp=(int*)msg.mtext; 34 | temp[0]=my_pid; 35 | temp[1]=state; 36 | temp[2]=index; 37 | msgsnd(msgid,&msg,sizeof(int)*3,0); 38 | //printf("send from %d to %d is\n",my_pid,des); 39 | } 40 | void msgreceive(int des) 41 | { 42 | msgrcv(msgid,&msg,sizeof(int)*3,des,0); 43 | int *temp=(int*)msg.mtext; 44 | get_pid=temp[0]; 45 | state=temp[1]; 46 | get_index=temp[2]; 47 | //printf("receive from %d to %d\n",des,my_pid); 48 | } 49 | void ok_function() 50 | { 51 | printf("等待顾客...\n"); 52 | msgreceive(4); 53 | msgsend(get_pid,OK,my_index); 54 | printf("为编号为%d的顾客理发...\n",get_index); 55 | getchar(); 56 | msgsend(get_pid,CHARGE,my_index); 57 | printf("理发完毕,结帐...\n"); 58 | semop(monid,&P,1); 59 | //结帐 60 | semop(monid,&V,1); 61 | msgsend(get_pid,END,my_index); 62 | printf("结帐完毕,送作顾客\n"); 63 | } 64 | main(int argc,char *argv[]) 65 | { 66 | name=(argv[1]==NULL)?"\0":argv[1]; 67 | msgid=msgget(MSGKEY,0777|IPC_CREAT); 68 | my_pid=getpid(); 69 | printf("%d\n",my_pid); 70 | P.sem_num=0; 71 | P.sem_op=-1; 72 | P.sem_flg=SEM_UNDO; 73 | V.sem_num=0; 74 | V.sem_op=1; 75 | V.sem_flg=SEM_UNDO; 76 | monid=semget(MONKEY,1,0666|IPC_CREAT); 77 | sen.val=1; 78 | semctl(monid,0,SETVAL,sen); //SETVAL设置信号量集中的一个单独的信号量的值 79 | printf("我是理发师%s我正在找理发店工作\n",name); 80 | msgsend(1,CUTTER,0); 81 | msgreceive(my_pid); 82 | my_index=get_index; 83 | if(state==FULL) 84 | printf("离开...\n"); 85 | else if(state==OK) 86 | { 87 | printf("加入了一个理发店...\n"); 88 | while(1) ok_function(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /ipc/semaphore/test3/test3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define SHM_KEY 0x33 7 | #define SEM_KEY 0x44 8 | 9 | union semun { 10 | int val; 11 | struct semid_ds *buf; 12 | unsigned short *array; 13 | }; 14 | 15 | int P(int semid) 16 | { 17 | struct sembuf sb; 18 | sb.sem_num = 0; 19 | sb.sem_op = -1; 20 | sb.sem_flg = SEM_UNDO; 21 | 22 | if(semop(semid, &sb, 1) == -1) { 23 | perror("semop"); 24 | return -1; 25 | } 26 | return 0; 27 | } 28 | 29 | int V(int semid) 30 | { 31 | struct sembuf sb; 32 | sb.sem_num = 0; 33 | sb.sem_op = 1; 34 | sb.sem_flg = SEM_UNDO; 35 | 36 | if(semop(semid, &sb, 1) == -1) { 37 | perror("semop"); 38 | return -1; 39 | } 40 | return 0; 41 | } 42 | 43 | int main(int argc, char **argv) 44 | { 45 | pid_t pid; 46 | int i, shmid, semid; 47 | int *ptr; 48 | union semun semopts; 49 | 50 | /* 创建一块共享内存, 存一个int变量 */ 51 | if ((shmid = shmget(SHM_KEY, sizeof(int), IPC_CREAT | 0600)) == -1) { 52 | perror("msgget"); 53 | } 54 | 55 | /* 将共享内存映射到进程, fork后子进程可以继承映射 */ 56 | if ((ptr = (int *)shmat(shmid, NULL, 0)) == (void *)-1) { 57 | perror("shmat"); 58 | } 59 | *ptr = 0; 60 | 61 | /* 创建一个信号量用来同步共享内存的操作 */ 62 | if ((semid = semget(SEM_KEY, 1, IPC_CREAT | 0600)) == -1) { 63 | perror("semget"); 64 | } 65 | 66 | /* 初始化信号量 */ 67 | semopts.val = 1; 68 | if (semctl(semid, 0, SETVAL, semopts) < 0) { 69 | perror("semctl"); 70 | } 71 | 72 | if ((pid = fork()) < 0) { 73 | perror("fork"); 74 | } else if (pid == 0) { /* Child */ 75 | /* 子进程对共享内存加1 */ 76 | for (i = 0; i < 100; i++) { 77 | P(semid); 78 | (*ptr)++; 79 | V(semid); 80 | printf("child: %d\n", *ptr); 81 | } 82 | } else { /* Parent */ 83 | /* 父进程对共享内存减1 */ 84 | for (i = 0; i < 100; i++) { 85 | P(semid); 86 | (*ptr)--; 87 | V(semid); 88 | printf("parent: %d\n", *ptr); 89 | } 90 | waitpid(pid); 91 | sleep(2); 92 | /* 如果同步成功, 共享内存的值为0 */ 93 | printf("finally: %d\n", *ptr); 94 | } 95 | 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /ipc/ShareMemory/server/server.c: -------------------------------------------------------------------------------- 1 | /*server.c:向共享内存中写入People*/ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "credis.h" 9 | 10 | int semid; 11 | int shmid; 12 | 13 | /*信号量的P操作*/ 14 | void p() 15 | { 16 | struct sembuf sem_p; 17 | sem_p.sem_num=0;/*设置哪个信号量*/ 18 | sem_p.sem_op=-1;/*定义操作*/ 19 | if(semop(semid,&sem_p,1)==-1) 20 | printf("p operation is fail\n"); 21 | /*semop函数自动执行信号量集合上的操作数组。 22 |    int semop(int semid, struct sembuf semoparray[], size_t nops); 23 |    semoparray是一个指针,它指向一个信号量操作数组。nops规定该数组中操作的数量。*/ 24 | } 25 | 26 | /*信号量的V操作*/ 27 | void v() 28 | { 29 | struct sembuf sem_v; 30 | sem_v.sem_num=0; 31 | sem_v.sem_op=1; 32 | if(semop(semid,&sem_v,1)==-1) 33 | printf("v operation is fail\n"); 34 | } 35 | 36 | int main() 37 | { 38 | struct People{ 39 | char name[10]; 40 | int age; 41 | }; 42 | 43 | key_t semkey; 44 | key_t shmkey; 45 | semkey=ftok("../test/VenusDB.cbp",0); //用来产生唯一的标志符,便于区分信号量及共享内存 46 | shmkey=ftok("../test/main.c",0); 47 | 48 | /*创建信号量的XSI IPC*/ 49 | semid=semget(semkey,1,0666|IPC_CREAT);//参数nsems,此时为中间值1,指定信号灯集包含信号灯的数目 50 | //0666|IPC_CREAT用来表示对信号灯的读写权限 51 | /* 52 | 从左向右: 53 | 第一位:0表示这是一个8进制数 54 | 第二位:当前用户的经权限:6=110(二进制),每一位分别对就 可读,可写,可执行,6说明当前用户可读可写不可执行 55 | 第三位:group组用户,6的意义同上 56 | 第四位:其它用户,每一位的意义同上,0表示不可读不可写也不可执行 57 | */ 58 | if(semid==-1) 59 | printf("creat sem is fail\n"); 60 | //创建共享内存 61 | shmid=shmget(shmkey,1024,0666|IPC_CREAT);//对共享内存 62 | if(shmid==-1) 63 | printf("creat shm is fail\n"); 64 | 65 | /*设置信号量的初始值,就是资源个数*/ 66 | union semun{ 67 | int val; 68 | struct semid_ds *buf; 69 | unsigned short *array; 70 | }sem_u; 71 | 72 | sem_u.val=1; /*设置变量值*/ 73 | semctl(semid,0,SETVAL,sem_u); //初始化信号量,设置第0个信号量,p()操作为非阻塞的 74 | 75 | /*将共享内存映射到当前进程的地址中,之后直接对进程中的地址addr操作就是对共享内存操作*/ 76 | 77 | struct People *addr; 78 | addr=(struct People*)shmat(shmid,0,0); //将共享内存映射到调用此函数的内存段 79 | if(addr==(struct People*)-1) 80 | printf("shm shmat is fail\n"); 81 | 82 | /*向共享内存写入数据*/ 83 | p(); 84 | strcpy((*addr).name,"xiaoming"); 85 | /*注意:①此处只能给指针指向的地址直接赋值,不能在定义一个 struct People people_1;addr=&people_1;因为addr在addr=(struct People*)shmat(shmid,0,0);时,已经由系统自动分配了一个地址,这个地址与共享内存相关联,所以不能改变这个指针的指向,否则他将不指向共享内存,无法完成通信了。 86 | 注意:②给字符数组赋值的方法。刚才太虎了。。*/ 87 | (*addr).age=10; 88 | v(); 89 | 90 | /*将共享内存与当前进程断开*/ 91 | if(shmdt(addr)==-1) 92 | printf("shmdt is fail\n"); 93 | } 94 | -------------------------------------------------------------------------------- /ipc/queue/cutter_customer/desk.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define MSGKEY 66 7 | #define MONKEY 88 8 | enum{CUTTER,CUSTOMERIN,CUSTOMERLEAVE,ROOM,SEAT,WORK,FULL,CHARGE,END,OK}; 9 | int my_pid; 10 | int get_pid; 11 | int state; 12 | int my_index; 13 | int get_index; 14 | int msgid; 15 | int monid; 16 | int cutter; //the number of cutter 17 | int cutterindex; 18 | int customer; //the number of customer 19 | int customerindex; 20 | char *name; 21 | struct msgform{ 22 | long mtype; 23 | char mtext[40]; 24 | }msg; 25 | union senum{ 26 | int val; 27 | }sen; 28 | void msgsend(int des,int state,int index) 29 | { 30 | msg.mtype=des; 31 | int *temp=(int*)msg.mtext; 32 | temp[0]=my_pid; 33 | temp[1]=state; 34 | temp[2]=index; 35 | msgsnd(msgid,&msg,sizeof(int)*3,0); 36 | //printf("send from %d to %d\n",my_pid,des); 37 | } 38 | void msgreceive(int des) 39 | { 40 | msgrcv(msgid,&msg,sizeof(int)*3,des,0); 41 | int *temp=(int*)msg.mtext; 42 | get_pid=temp[0]; 43 | state=temp[1]; 44 | get_index=temp[2]; 45 | //printf("receive from %d to %d\n",des,my_pid); 46 | } 47 | void cutter_function() 48 | { 49 | if(cutter>=1) 50 | msgsend(get_pid,FULL,0); 51 | else if(cutter>=0) 52 | { 53 | msgsend(get_pid,OK,++cutterindex); 54 | printf("一名理发师加入本店,为其编号%d\n",cutterindex); 55 | ++cutter; 56 | } 57 | else 58 | printf("ERROR1\n"); 59 | } 60 | void customerin_function() 61 | { 62 | if(customer>=3) 63 | msgsend(get_pid,FULL,0); 64 | else if(customer>=2) 65 | { 66 | msgsend(get_pid,ROOM,++customerindex); 67 | printf("一名顾客来到理发店在大厅等候,为其编号%d\n",customerindex); 68 | ++customer; 69 | } 70 | else if(customer>=1) 71 | { 72 | msgsend(get_pid,SEAT,++customerindex); 73 | printf("一名顾客来到理发店在座位上等候,为其编号%d\n",customerindex); 74 | ++customer; 75 | } 76 | else if(customer>=0) 77 | { 78 | msgsend(get_pid,WORK,++customerindex); 79 | printf("一名顾客来到理发店开始理发,为其编号%d\n",customerindex); 80 | ++customer; 81 | } 82 | else 83 | printf("ERROR2\n"); 84 | } 85 | void customerleave_function() 86 | { 87 | printf("一名顾客离开本店,其编号为%d\n",get_index); 88 | printf("customer:%d\n",customer); 89 | if(customer>1) 90 | { 91 | msgreceive(2); 92 | msgsend(get_pid,WORK,get_index); 93 | printf("编号为%d的顾客从座位上坐起来去理发\n",get_index); 94 | } 95 | if(customer>2) 96 | { 97 | msgreceive(3); 98 | msgsend(get_pid,SEAT,get_index); 99 | printf("编号为%d的顾客从大厅坐到了座位上继续等待\n",get_index); 100 | } 101 | if(customer>3) 102 | printf("ERROR3\n"); 103 | --customer; 104 | } 105 | main(int argc,char *argv[]) 106 | { 107 | name=(argv[1]==NULL)?"\0":argv[1]; 108 | my_pid=getpid(); 109 | msgid=msgget(MSGKEY,0777|IPC_CREAT); //用的不好,没有用到ftok去获取唯一键值 110 | /* 创建消息队列*/ 111 | while(1) 112 | { 113 | printf("目前有理发师%d名,顾客%d名\n",cutter,customer); 114 | msgreceive(1); 115 | if(state==CUTTER) 116 | cutter_function(); 117 | else if(state==CUSTOMERIN) 118 | customerin_function(); 119 | else if(state==CUSTOMERLEAVE) 120 | customerleave_function(); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ipc/semaphore/os_semaphere/mutex/mutex.c: -------------------------------------------------------------------------------- 1 | /* 2 | *date:2012-12-3 3 | *author:chermong 4 | *description:use orderly resource allocation method to resolve died lock problem 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define Max 10 //the most number of threads 13 | pthread_t E[Max];//the thread of E direction 14 | pthread_t W[Max];//the thread of W direction 15 | pthread_t S[Max];//the thread of S direction 16 | pthread_mutex_t a;//the mutex of A 17 | pthread_mutex_t b;//the mutex of B 18 | pthread_mutex_t c;//the mutex of C 19 | pthread_mutex_t d;//the mutex of D 20 | 21 | /* 22 | *args: 23 | * num:the number flag of the thread 24 | *doc:S derection 25 | */ 26 | void *s(int num) 27 | { 28 | pthread_mutex_lock(&c); 29 | printf("S %d enter C\n",num); 30 | sleep(2); 31 | pthread_mutex_lock(&b); 32 | printf("S %d enter B\n",num); 33 | pthread_mutex_unlock(&c); 34 | sleep(2); 35 | pthread_mutex_lock(&a); 36 | printf("S %d enter A\n",num);//note:the order of the unlocked sentence and the printf sentence 37 | pthread_mutex_unlock(&b); 38 | sleep(2); 39 | printf("S %d leave A\n",num); 40 | printf("!!!S finished one\n"); 41 | pthread_mutex_unlock(&a); 42 | } 43 | 44 | /* 45 | *args: 46 | * num:the number flag of the thread 47 | *doc:E derection 48 | */ 49 | void *e(int num) 50 | { 51 | pthread_mutex_lock(&b); 52 | printf("E %d enter B\n",num); 53 | sleep(2); 54 | pthread_mutex_lock(&a); 55 | printf("E %d enter A\n",num); 56 | pthread_mutex_unlock(&b); 57 | sleep(2); 58 | pthread_mutex_lock(&d); 59 | printf("E %d enter D\n",num); 60 | pthread_mutex_unlock(&a); 61 | sleep(2); 62 | printf("E %d leave D\n",num); 63 | printf("!!!E finished one\n"); 64 | pthread_mutex_unlock(&d); 65 | } 66 | 67 | /* 68 | *args: 69 | * num:the number flag of the thread 70 | *doc:W derection 71 | */ 72 | void *w(int num) 73 | { 74 | pthread_mutex_lock(&c); 75 | pthread_mutex_lock(&d); 76 | printf("W %d enter D\n",num); 77 | sleep(2); 78 | printf("W %d enter C\n",num); 79 | pthread_mutex_unlock(&d); 80 | sleep(2); 81 | printf("W %d leave C\n",num); 82 | printf("!!!W finished one\n"); 83 | pthread_mutex_unlock(&c); 84 | } 85 | 86 | int main(int argc,char *argv[]) 87 | { 88 | int carnum,i; 89 | 90 | printf("This program will help you let cars cross this T crossing.\n"); 91 | printf("Suppose that there are same quantity of cars in three derections.\n"); 92 | printf("Please input the integer number,less than %d:",Max); 93 | 94 | //enter the number of the threads of three direction 95 | scanf("%d",&carnum); 96 | if(carnum > Max) { 97 | printf("Please input the integer number,less than %d,try again\n",Max); 98 | exit(1); 99 | } 100 | 101 | //the mutexes becomes initialised and unlocked,success return 0 102 | if(pthread_mutex_init(&c,NULL) & pthread_mutex_init(&b,NULL) & pthread_mutex_init(&a,NULL) & pthread_mutex_init(&d,NULL)){ 103 | printf("Initialises the 4 mutexes error."); 104 | exit(1); 105 | } 106 | 107 | //create threads to work 108 | for(i = 0;i < carnum;i++) { 109 | pthread_create(&W[i],NULL,(void*)w,(void*)(i + 1)); 110 | pthread_create(&E[i],NULL,(void*)e,(void*)(i + 1)); 111 | pthread_create(&S[i],NULL,(void*)s,(void*)(i + 1)); 112 | sleep(5); 113 | } 114 | 115 | //make sure all the theads to finish before return in main thread. 116 | for(i = 0;i < carnum;i++) { 117 | pthread_join(W[i],NULL); 118 | pthread_join(E[i],NULL); 119 | pthread_join(S[i],NULL); 120 | } 121 | 122 | //the mutexes becomes destoryed,success return 0 123 | if(pthread_mutex_destroy(&c) & pthread_mutex_destroy(&b) & pthread_mutex_destroy(&a) & pthread_mutex_destroy(&d)){ 124 | printf("Destory the 4 mutexes error."); 125 | exit(1); 126 | } 127 | 128 | exit(0); 129 | } 130 | -------------------------------------------------------------------------------- /ipc/semaphore/test2/test2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #define MAX_SEMAPHORE 10 13 | #define FILE_NAME "test2.c" 14 | 15 | union semun{ 16 | int val ; 17 | struct semid_ds *buf ; 18 | unsigned short *array ; 19 | struct seminfo *_buf ; 20 | }arg; 21 | struct semid_ds sembuf; 22 | 23 | int main() 24 | { 25 | key_t key ; 26 | int semid ,ret,i; 27 | unsigned short buf[MAX_SEMAPHORE] ; 28 | struct sembuf sb[MAX_SEMAPHORE] ; 29 | pid_t pid ; 30 | 31 | pid = fork() ; 32 | if(pid < 0) 33 | { 34 | /* Create process Error! */ 35 | fprintf(stderr,"Create Process Error!:%s\n",strerror(errno)); 36 | exit(1) ; 37 | } 38 | if(pid > 0) 39 | { 40 | /* in parent process !*/ 41 | key = ftok(FILE_NAME,'a') ; 42 | if(key == -1) 43 | { 44 | /* in parent process*/ 45 | fprintf(stderr,"Error in ftok:%s!\n",strerror(errno)); 46 | exit(1) ; 47 | } 48 | 49 | semid = semget(key,MAX_SEMAPHORE,IPC_CREAT|0666); //创建信号量集合 50 | if(semid == -1) 51 | { 52 | fprintf(stderr,"Error in semget:%s\n",strerror(errno)); 53 | exit(1) ; 54 | } 55 | printf("Semaphore have been initialed successfully in parent process,ID is :%d\n",semid); 56 | sleep(2) ; 57 | printf("parent wake up....\n"); 58 | /*父进程在子进程得到semaphore的时候请求semaphore,此时父进程将阻塞直至子进程释放掉semaphore*/ 59 | /* 此时父进程的阻塞是因为semaphore 1 不能申请,因而导致的进程阻塞*/ 60 | for(i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define MYPORT 1234 // the port users will be connecting to 12 | 13 | #define BACKLOG 5 // how many pending connections queue will hold 14 | 15 | #define BUF_SIZE 200 16 | 17 | int fd_A[BACKLOG]; // accepted connection fd 18 | int conn_amount; // current connection amount 19 | 20 | //打印号码和对应的socket id 21 | void showclient() 22 | { 23 | int i; 24 | printf("client amount: %d\n", conn_amount); 25 | for (i = 0; i < BACKLOG; i++) { 26 | printf("[%d]:%d ", i, fd_A[i]); 27 | } 28 | printf("\n\n"); 29 | } 30 | 31 | int main(void) 32 | { 33 | int sock_fd, new_fd; // listen on sock_fd, new connection on new_fd 34 | struct sockaddr_in server_addr; // server address information 35 | struct sockaddr_in client_addr; // connector's address information 36 | socklen_t sin_size; 37 | int yes = 1; 38 | char buf[BUF_SIZE]; 39 | int ret; 40 | int i; 41 | 42 | if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 43 | perror("socket"); 44 | exit(1); 45 | } 46 | 47 | //the SO_REUSEADDR flag tells the kernel to reuse a local socket in TIME_WAIT state, without waiting for its natural timeout to expire. 48 | if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { 49 | perror("setsockopt"); 50 | exit(1); 51 | } 52 | 53 | server_addr.sin_family = AF_INET; // host byte order 54 | server_addr.sin_port = htons(MYPORT); // short, network byte order 55 | server_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP 56 | //INADDR_ANY就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”。也就是表示机器上的所用网络地址,比如你的机器上有两张网卡,那么到达这两张网卡的数据,你的socket都可以得到通知 57 | memset(server_addr.sin_zero, '\0', sizeof(server_addr.sin_zero)); 58 | 59 | if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { 60 | perror("bind"); 61 | exit(1); 62 | } 63 | //BACKLOG:The backlog argument defines the maximum length to which the queue of pending(等待的) connections for sockfd may grow. If a connection request arrives when the queue is full, the client may receive an error with an indication of ECONNREFUSED or, if the underlying protocol supports retransmission, the request may be ignored so that a later reattempt at connection succeeds. 64 | if (listen(sock_fd, BACKLOG) == -1) { 65 | perror("listen"); 66 | exit(1); 67 | } 68 | 69 | printf("listen port %d\n", MYPORT); 70 | 71 | fd_set fdsr; 72 | int maxsock; 73 | struct timeval tv; 74 | 75 | conn_amount = 0; 76 | sin_size = sizeof(client_addr); 77 | maxsock = sock_fd; 78 | 79 | //为了验证最初fd_A中全部为0 80 | //for (i = 0; i < BACKLOG; i++) { 81 | // printf("%d\n",fd_A[i]); 82 | //} 83 | 84 | while (1) { 85 | // initialize file descriptor set 86 | FD_ZERO(&fdsr); 87 | FD_SET(sock_fd, &fdsr); 88 | 89 | // timeout setting 90 | tv.tv_sec = 30; 91 | tv.tv_usec = 0; 92 | 93 | // add active connection to fd set 94 | for (i = 0; i < BACKLOG; i++) { 95 | if (fd_A[i] != 0) { 96 | FD_SET(fd_A[i], &fdsr); 97 | } 98 | } 99 | 100 | ret = select(maxsock + 1, &fdsr, NULL, NULL, &tv);//当调用select()时,由内核根据io状态修改fd_set的内容. 101 | if (ret < 0) { 102 | perror("select"); 103 | break; 104 | } else if (ret == 0) { 105 | printf("timeout\n"); 106 | continue; 107 | } 108 | 109 | // check every fd in the set 110 | for (i = 0; i < conn_amount; i++) { 111 | if (FD_ISSET(fd_A[i], &fdsr)) { 112 | ret = recv(fd_A[i], buf, sizeof(buf), 0); 113 | if (ret <= 0) { // client close 114 | printf("client[%d] close\n", i); 115 | close(fd_A[i]); 116 | FD_CLR(fd_A[i], &fdsr); 117 | fd_A[i] = 0; 118 | } else { // receive data 119 | if (ret < BUF_SIZE) 120 | memset(&buf[ret], '\0', 1); 121 | printf("client[%d] send:%s\n", i, buf); 122 | } 123 | } 124 | } 125 | 126 | // check whether a new connection comes 127 | if (FD_ISSET(sock_fd, &fdsr)) { 128 | //The accept() system call is used with connection-based socket types (SOCK_STREAM, SOCK_SEQPACKET). It extracts the first connection request on the queue of pending connections for the listening socket, sockfd, creates a new connected socket, and returns a new file descriptor referring to that socket. The newly created socket is not in the listening state. The original socket sockfd is unaffected by this call. 129 | new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size); 130 | if (new_fd <= 0) { 131 | perror("accept"); 132 | continue; 133 | } 134 | 135 | // add to fd queue 136 | if (conn_amount < BACKLOG) { 137 | fd_A[conn_amount++] = new_fd; 138 | printf("new connection client[%d] %s:%d\n", conn_amount, 139 | inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); 140 | if (new_fd > maxsock) 141 | maxsock = new_fd; 142 | } 143 | else { 144 | printf("max connections arrive, exit\n"); 145 | send(new_fd, "bye", 4, 0); 146 | close(new_fd); 147 | break; 148 | } 149 | } 150 | showclient();//打印号码和对应的socket id 151 | } 152 | 153 | // close other connections 154 | for (i = 0; i < BACKLOG; i++) { 155 | if (fd_A[i] != 0) { 156 | close(fd_A[i]); 157 | } 158 | } 159 | 160 | exit(0); 161 | } 162 | -------------------------------------------------------------------------------- /ipc/select_poll/select_detail/select_detail.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | static int forward_port; 14 | 15 | #undef max 16 | #define max(x,y) ((x) > (y) ? (x) : (y)) 17 | 18 | static int 19 | listen_socket(int listen_port) 20 | { 21 | struct sockaddr_in a; 22 | int s; 23 | int yes; 24 | 25 | if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 26 | perror("socket"); 27 | return -1; 28 | } 29 | yes = 1; 30 | if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 31 | (char *) &yes, sizeof(yes)) == -1) { 32 | perror("setsockopt"); 33 | close(s); 34 | return -1; 35 | } 36 | memset(&a, 0, sizeof(a)); 37 | a.sin_port = htons(listen_port); 38 | a.sin_family = AF_INET; 39 | if (bind(s, (struct sockaddr *) &a, sizeof(a)) == -1) { 40 | perror("bind"); 41 | close(s); 42 | return -1; 43 | } 44 | printf("accepting connections on port %d\n", listen_port); 45 | listen(s, 10); 46 | return s; 47 | } 48 | 49 | static int 50 | connect_socket(int connect_port, char *address) 51 | { 52 | struct sockaddr_in a; 53 | int s; 54 | 55 | if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 56 | perror("socket"); 57 | close(s); 58 | return -1; 59 | } 60 | 61 | memset(&a, 0, sizeof(a)); 62 | a.sin_port = htons(connect_port); 63 | a.sin_family = AF_INET; 64 | 65 | if (!inet_aton(address, (struct in_addr *) &a.sin_addr.s_addr)) { 66 | perror("bad IP address format"); 67 | close(s); 68 | return -1; 69 | } 70 | 71 | if (connect(s, (struct sockaddr *) &a, sizeof(a)) == -1) { 72 | perror("connect()"); 73 | shutdown(s, SHUT_RDWR); 74 | close(s); 75 | return -1; 76 | } 77 | return s; 78 | } 79 | 80 | #define SHUT_FD1 do { \ 81 | if (fd1 >= 0) { \ 82 | shutdown(fd1, SHUT_RDWR); \ 83 | close(fd1); \ 84 | fd1 = -1; \ 85 | } \ 86 | } while (0) 87 | 88 | #define SHUT_FD2 do { \ 89 | if (fd2 >= 0) { \ 90 | shutdown(fd2, SHUT_RDWR); \ 91 | close(fd2); \ 92 | fd2 = -1; \ 93 | } \ 94 | } while (0) 95 | 96 | #define BUF_SIZE 1024 97 | 98 | int 99 | main(int argc, char *argv[]) 100 | { 101 | int h; 102 | int fd1 = -1, fd2 = -1; 103 | char buf1[BUF_SIZE], buf2[BUF_SIZE]; 104 | int buf1_avail, buf1_written; 105 | int buf2_avail, buf2_written; 106 | 107 | if (argc != 4) { 108 | fprintf(stderr, "Usage\n\tfwd " 109 | " \n"); 110 | exit(EXIT_FAILURE); 111 | } 112 | 113 | signal(SIGPIPE, SIG_IGN); 114 | 115 | forward_port = atoi(argv[2]); 116 | 117 | h = listen_socket(atoi(argv[1])); 118 | if (h == -1) 119 | exit(EXIT_FAILURE); 120 | 121 | for (;;) { 122 | int r, nfds = 0; 123 | fd_set rd, wr, er; 124 | 125 | FD_ZERO(&rd); 126 | FD_ZERO(&wr); 127 | FD_ZERO(&er); 128 | FD_SET(h, &rd); 129 | nfds = max(nfds, h); 130 | if (fd1 > 0 && buf1_avail < BUF_SIZE) { 131 | FD_SET(fd1, &rd); 132 | nfds = max(nfds, fd1); 133 | } 134 | if (fd2 > 0 && buf2_avail < BUF_SIZE) { 135 | FD_SET(fd2, &rd); 136 | nfds = max(nfds, fd2); 137 | } 138 | if (fd1 > 0 && buf2_avail - buf2_written > 0) { 139 | FD_SET(fd1, &wr); 140 | nfds = max(nfds, fd1); 141 | } 142 | if (fd2 > 0 && buf1_avail - buf1_written > 0) { 143 | FD_SET(fd2, &wr); 144 | nfds = max(nfds, fd2); 145 | } 146 | if (fd1 > 0) { 147 | FD_SET(fd1, &er); 148 | nfds = max(nfds, fd1); 149 | } 150 | if (fd2 > 0) { 151 | FD_SET(fd2, &er); 152 | nfds = max(nfds, fd2); 153 | } 154 | 155 | r = select(nfds + 1, &rd, &wr, &er, NULL); 156 | 157 | if (r == -1 && errno == EINTR) 158 | continue; 159 | 160 | if (r == -1) { 161 | perror("select()"); 162 | exit(EXIT_FAILURE); 163 | } 164 | 165 | if (FD_ISSET(h, &rd)) { 166 | unsigned int l; 167 | struct sockaddr_in client_address; 168 | 169 | memset(&client_address, 0, l = sizeof(client_address)); 170 | r = accept(h, (struct sockaddr *) &client_address, &l); 171 | if (r == -1) { 172 | perror("accept()"); 173 | } else { 174 | SHUT_FD1; 175 | SHUT_FD2; 176 | buf1_avail = buf1_written = 0; 177 | buf2_avail = buf2_written = 0; 178 | fd1 = r; 179 | fd2 = connect_socket(forward_port, argv[3]); 180 | if (fd2 == -1) 181 | SHUT_FD1; 182 | else 183 | printf("connect from %s\n", 184 | inet_ntoa(client_address.sin_addr)); 185 | } 186 | } 187 | 188 | /* NB: read oob data before normal reads */ 189 | 190 | if (fd1 > 0) 191 | if (FD_ISSET(fd1, &er)) { 192 | char c; 193 | 194 | r = recv(fd1, &c, 1, MSG_OOB); 195 | if (r < 1) 196 | SHUT_FD1; 197 | else 198 | send(fd2, &c, 1, MSG_OOB); 199 | } 200 | if (fd2 > 0) 201 | if (FD_ISSET(fd2, &er)) { 202 | char c; 203 | 204 | r = recv(fd2, &c, 1, MSG_OOB); 205 | if (r < 1) 206 | SHUT_FD2; 207 | else 208 | send(fd1, &c, 1, MSG_OOB); 209 | } 210 | if (fd1 > 0) 211 | if (FD_ISSET(fd1, &rd)) { 212 | r = read(fd1, buf1 + buf1_avail, 213 | BUF_SIZE - buf1_avail); 214 | if (r < 1) 215 | SHUT_FD1; 216 | else 217 | buf1_avail += r; 218 | } 219 | if (fd2 > 0) 220 | if (FD_ISSET(fd2, &rd)) { 221 | r = read(fd2, buf2 + buf2_avail, 222 | BUF_SIZE - buf2_avail); 223 | if (r < 1) 224 | SHUT_FD2; 225 | else 226 | buf2_avail += r; 227 | } 228 | if (fd1 > 0) 229 | if (FD_ISSET(fd1, &wr)) { 230 | r = write(fd1, buf2 + buf2_written, 231 | buf2_avail - buf2_written); 232 | if (r < 1) 233 | SHUT_FD1; 234 | else 235 | buf2_written += r; 236 | } 237 | if (fd2 > 0) 238 | if (FD_ISSET(fd2, &wr)) { 239 | r = write(fd2, buf1 + buf1_written, 240 | buf1_avail - buf1_written); 241 | if (r < 1) 242 | SHUT_FD2; 243 | else 244 | buf1_written += r; 245 | } 246 | 247 | /* check if write data has caught read data */ 248 | 249 | if (buf1_written == buf1_avail) 250 | buf1_written = buf1_avail = 0; 251 | if (buf2_written == buf2_avail) 252 | buf2_written = buf2_avail = 0; 253 | 254 | /* one side has closed the connection, keep 255 | writing to the other side until empty */ 256 | 257 | if (fd1 < 0 && buf1_avail - buf1_written == 0) 258 | SHUT_FD2; 259 | if (fd2 < 0 && buf2_avail - buf2_written == 0) 260 | SHUT_FD1; 261 | } 262 | exit(EXIT_SUCCESS); 263 | } 264 | --------------------------------------------------------------------------------