多进程socket服务器(c语言)

一、进程
1.进程是动态的,是程序的一次运行活动。

2.进程在内存中由数据段、堆栈段和代码段组成。c程序内存分布图如下
在这里插入图片描述

3.每个进程都有自己的进程标识符pid,可以调用getpid()来得到自己的pid,getppid()获得父进程的标识符

4.创建子进程:
pid_t fork(void);
fork函数调用一次返回两次,子进程的返回值是0,父进程的返回值是子进程的PID,因此通常利用这个区别去设置判断语句令父子进程执行不同的操作。一般来说,fork之后的父子进程的执行顺序是不确定的,这个取决于调度算法。
fork之后的处理方法:

  • fork之后子进程和父进程处理不同的代码段
  • fork之后调用exec,让子进程处理完全不同的程序

pid_t vfork(void);

vfork创建一个子进程,但是该子进程并不对父进程地址空间进行拷贝而是直接共享。因此如果让子进程对父进程数据进行读或写都可能产生段错误。主要原因在于,因为vfork产生的子进程是要exec一个新程序的,于是也就不会引用该地址空间了,不过子进程再调用exec()或
exit()之前,他将在父进程的空间中运行,但如果子进程想尝试修改数据域(数据段、堆、栈)都会带来未知的结果,就算写实复制copyonwrite(COW)( 这些数据区域由父子进程共享,内核将他们的访问权限改成只读,如果父进程和子进程中的任何一个试图修改这些区域的时候,内核再为修改区域的那块内存制作一个副本。)机制也不如索性不复制节约时间。

vfork保证子进程先运行,在它调用exec或者exit后父进程才可以被调用执

5.wait()和waitpid()
pid_t wait(int *status);
当一个进程正常或异常退出时,内核就会向其父进程发送SIGCHLD信号。因为子进程退出是一个异步事件,所以这种信号也是内核向父进程发送的一个异步通知。父进程可以选择忽略该信号,或者提供一个该信号发生时即将被执行的函数,父进程可以调用wait()或waitpid()可以用来查看子进程退出的状态。进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
参数:
参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针止。但如果我们对这个子进程是如何死掉的毫不在意,只想把这个僵尸进程消灭掉,可以直接传NULL。
返回值:
如果成功,wait会返回被收集的子进程的进程ID
如果调用进程没有子进程,调用就会失败,此时wait返回-1,同时errno被置为ECHILD。

pid_t waitpid(pid_t pid,int *status,int options);
系统调用waitpid和wait的作用是完全相同的,但waitpid多出了两个可由用户控制的参数pid和options,提供了另一种更灵活的方式。
二、使用多进程编程改写服务器的流程如下:
在这里插入图片描述

**服务器端的代码如下:**
/*********************************************************************************
 *      Copyright:  (C) 2021 jiaoer237
 *                  All rights reserved.
 *
 *       Filename:  socket_server_fork.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(11/23/2021)
 *         Author:  yanp <2405204881@qq.com>
 *      ChangeLog:  1, Release initial version on "11/23/2021 04:35:39 PM"
 *                 
 ********************************************************************************/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <getopt.h>

#define MSG_STR "Hello yanp\n"
#define BACKLOG 13

void printf_usage(char *program);
int socket_init(char *listen_ip,int listen_port);

int main(int argc,char **argv)
{
   
    int daemon_run=0;
    char *program;
    int serv_port=0;
    int listen_fd;
    int clifd=-1;
    int rv=-2;
    int opt;

    struct sockaddr_in cliaddr;
    socklen_t cliaddr_len;
    pid_t pid;

    struct option long_options[] =/*参数解析包括需要监听的端口号和是否在后台运行*/
    {
   
        {
   "daemon", no_argument, NULL, 'b'},
        {
   "port", required_argument, NULL, 'p'},
        {
   "help", no_argument, NULL, 'h'},
        {
   NULL, 0, NULL, 0}
    };

    program=argv[0];
    while((opt = getopt_long(argc, argv, "bp:h", long_options, NULL)) != -1)
    {
   
        switch(opt)
        {
   
            case 'b':
                daemon_run=1;
                break;
            case 'p':
                serv_port = atoi(optarg);/*将字符串转换成整型*/
                break
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值