进程间通信–共享内存篇

池的服务器程序 下面做了非常简单的http服务器,该服务器只能接收Get请求。 流程大概如下: 1,父

listen,创建pipe(下面所有父子

都用该pipe) 2,父

预fork n个子

3,各个子

accept(listenfd),即所有子

竞争accept请求。由于listenfd是在fork之前就有的,所以所有子

都可以访问到,不需用到”

文件描述符传递”问题; 4,子

每accept到一个请求都告诉父

把请求数加1;子

没完成一个请求,父

把请求数减1;当父

发现请求数 >= 子

数时,父

创建新的子

,并把子

数加1(当然子

数有个预先上限);当父

发现子

数大于请求数加1时,父

杀死多余的子

。 总的来说,思想是让子

accept并处理请求,父

通过子

发来的信息控制请求数与子

的关系。 代码如下: 代码如下: #include

accept请求 rep.status = ‘n’; if (write(fd1[1], &rep, sizeof(rep)) < 0) { //通知父

已经accept了请求 perror(“write pipe new failed”); exit(-1); } count = read(connfd, buf, BUFSIZE); char req[10]; char filepath[256]; sscanf(buf, “%s%s”, req, filepath + 1); filepath[0] = ‘.’; if (strcmp(“GET”, req) != 0) {//503 write(connfd, head503, len503); //goto err_out; close(connfd); exit(-1); } char content[BUFSIZE]; struct stat stbuf; if (lstat(filepath, &stbuf) != 0) { int err = errno; if (err == ENOENT) {//404 write(connfd, head404, len404); } close(connfd); exit(-1); } count = write(connfd, head200, len200); u_int filesize = stbuf.st_size; sprintf(content, “%u\n\r\n\r”, filesize); count = write(connfd, content, strlen(content)); FILE *fp = fopen(filepath, “r”); if (fp == NULL) { printf(“open file %s failed\n”, filepath); close(connfd); exit(-1); } while((count = fread(content, 1, sizeof(content), fp)) > 0) { //printf(“%s”, content); if (write(connfd, content, count) != count) { printf(“write failed\n”); } } fclose(fp); close(connfd); rep.status = ‘f’; if (write(fd1[1], &rep, sizeof(rep)) < 0) {//告诉父

自己处理完了请求 perror(“write pipe finish failed”); exit(-1); } if (read(fd2[0], &comm, 1) < 1) {//等待来自父

的命令 perror(“read pipe failed”); exit(-1); } //printf(“[%d] reve %c from pa\n”, pid, comm); if (comm == ‘e’) { //收到exit命令 printf(“[%d] exit\n”, pid); exit(-1); } else if (comm == ‘c’) { //收到继续accept的命令 printf(“[%d] continue\n”, pid); } else { printf(“[%d] comm : %c illeagle\n”, pid, comm); } } } void usage() { printf(“Usage: http-serv port\n”); } int write_pid() { int fd; if ((fd = open(PIDPATH, O_WRONLY | O_TRUNC | O_CREAT, S_IWUSR)) < 0){ perror(“open pidfile faild”); return -1; } struct flock lock; lock.l_type = F_WRLCK; lock.l_start = 0; lock.l_whence = SEEK_SET; lock.l_len = 0; if (fcntl(fd, F_SETLK, &lock) == -1) { int err = errno; perror(“fcntl faild”); if (err == EAGAIN) { printf(“Another http-serv process is running now!\n”); } return -1; } return 0; } void daemon_init() { //clear file creation mask; umask(0); //become a session leader if (fork() != 0) exit(-1); if (setsid() < 0) exit(-1); //make sure can be never get the TTY control if (fork() != 0) exit(-1); //may chdir here int i; for (i = 0; i < 1024; i++) close(i); / * Attach file descriptors 0, 1, and 2 to /dev/null. / int fd0, fd1, fd2; fd0 = open(“/dev/null”, O_RDWR); fd1 = dup(0); fd2 = dup(0); if (fd0 != 0 || fd1 != 1 || fd2 != 2) { printf(“init failed\n”); exit(-1); } } int main(int argc, char *argv) { int listenfd; struct sockaddr_in servaddr; pid_t pid; if (argc != 2) { usage(); return -1; } signal(SIGCHLD, SIG_IGN); len200 = strlen(head200); len404 = strlen(head404); len503 = strlen(head503); daemon_init(); //转为后台程序,如需打印调试,把这行注释掉 if (write_pid() < 0) //避免同时有多个该程序在运行 return -1; if (pipe(fd1) < 0) { perror(“pipe failed”); exit(-1); } if (s_pipe(fd2) < 0) { perror(“pipe failed”); exit(-1); } int port = atoi(argv[1]); //initialize servaddr and listenfd… bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(port); listenfd = socket(AF_INET, SOCK_STREAM, 0); bind(listenfd, (struct sockaddr ) &servaddr, sizeof(servaddr)); listen(listenfd, 1000); int i; for (i = 0; i < PRECHILD ; i++) { //父

预fork 子

if ((pid = fork()) < 0) { perror(“fork faild”); exit(3); } else if (pid == 0) { answer(listenfd); } else { printf(“have create child %d\n”, pid); } } char e = ‘e’; char c = ‘c’; int req_num = 0; int child_num = PRECHILD; REPORT rep; while (1) { //printf(“req_num = %d, child_num = %d\n”, req_num, child_num); if (read(fd1[0], &rep, sizeof(rep)) < sizeof(rep)) {//等待子

发来消息 perror(“parent read pipe failed”); exit(-1); } //printf(“parent: receive from %d\n”, pid); if (rep.status == ‘n’) {//子

刚accept了新的请求 req_num ++; printf(“parent: %d have receive new request\n”, rep.pid); if (req_num >= child_num && child_num

Original: https://blog.csdn.net/qq_63412763/article/details/128334472
Author: 皮皮蜥
Title: 进程间通信–共享内存篇

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/795143/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球