不同linux操作系统的内存管理及安全性

不同linux操作系统的内存管理及安全性

20191331 lyx

1.前言

今天编程时遇到一个非常有趣的现象————编写了一个socket网络通信程序,使用一台虚拟机(openeuler 20.03 LTS)做客户端,另外一台云服务器(Ubuntu 18.04 server 64bit with ARM)和一台虚拟机(kali linux4.19.0-kali4-amd64 )做服务端。程序非常简单,即客户端和服务端建立socket连接,服务端返回当前时间。但却出现了两种实验结果。

环境:

代码如下:

********************client.c*************************
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>    
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include <net/if.h>
#include <sys/ioctl.h>

#define RIO_BUFSIZE 8192

typedef struct sockaddr SA;
typedef struct{
    int rio_fd;
    int rio_cnt;
    char *rio_bufptr;
    char rio_buf[RIO_BUFSIZE];

}rio_t;

#define MAXLINE 200

int get_local_ip(const char *eth_inf,char *ipBuf)
{
    int sd;
    struct sockaddr_in sin;
    struct ifreq ifr;
 
    sd = socket(AF_INET, SOCK_DGRAM, 0);
    if (-1 == sd)
    {
        printf("socket error: %s\n", strerror(errno));
        return -1;
    }
 
    strncpy(ifr.ifr_name, eth_inf, IFNAMSIZ);
    ifr.ifr_name[IFNAMSIZ - 1] = 0;
 
    // if error: No such device  
    if (ioctl(sd, SIOCGIFADDR, &ifr) < 0)
    {
        printf("ioctl error: %s\n", strerror(errno));
        close(sd);
        return -1;
    }
    
    snprintf(ipBuf ,50,"%s" ,inet_ntoa(((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr)); 

    close(sd);
    return 0;
}


int open_clientfd(char *hostname,int port){

    int clientfd;
    struct hostent *hp;
    struct sockaddr_in serveraddr;

    if((clientfd = socket(AF_INET,SOCK_STREAM,0))<0)
        return -1;

    if((hp = gethostbyname(hostname))==NULL)
        return -2;

    bzero((char *)&serveraddr,sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    bcopy((char *)hp->h_addr_list[0],
            (char *)&serveraddr.sin_addr.s_addr,hp->h_length);
    serveraddr.sin_port = htons(port);

    if(connect(clientfd,(SA *)&serveraddr,sizeof(serveraddr))<0)
        return -1;
    
    return clientfd;
}



int main(int argc,char **argv){

    int clientfd,port;
    char *host,buf[MAXLINE];
    char myhost[32] = "";
    char sbuf[MAXLINE];
    char rbuf[MAXLINE];
    rio_t rio;
    char str1[MAXLINE]="Client IP:";
    char str2[MAXLINE]="Server Implementer:20191331";
    
    char str3[MAXLINE]="Current Time:";

    if(argc!=3){
    
        fprintf(stderr,"usage:%s <host> <port>\n",argv[0]);
        exit(0);
    }
    get_local_ip("enp0s3",myhost);
    host = argv[1];
    port = atoi(argv[2]);

    clientfd = open_clientfd(host,port);
  
    while(1){
        

        recv(clientfd,rbuf,MAXLINE,0);

        printf("%s",str1);
        puts(myhost);

        printf("%s",str2);
        putchar('\n');

        printf("%s",str3);
      
        puts(rbuf);
       
        close(clientfd);
       
        exit(0);
    }

}

*************************server.c************************
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>    
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include <net/if.h>
#include <sys/ioctl.h>

#define MAXLINE 200
#define RIO_BUFSIZE 8192
#define LISTENQ 1024

typedef struct{
    int rio_fd;
    int rio_cnt;
    char *rio_bufptr;
    char rio_buf[RIO_BUFSIZE];

}rio_t;
typedef struct sockaddr SA;

typedef struct{
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
}tm;

int open_listenfd(int port){

    int listenfd,optval=1;
    struct sockaddr_in serveraddr;

    if((listenfd = socket(AF_INET,SOCK_STREAM,0))<0)
        return -1;

    if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,
                (const void*)&optval,sizeof(int))<0)
        return -1;

    bzero((char *)&serveraddr,sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port = htons((unsigned short)port);
    if(bind(listenfd,(SA*)&serveraddr,sizeof(serveraddr))<0)
        return -1;

    if(listen(listenfd,LISTENQ)<0)
        return -1;

    return listenfd;
}


void sigchld_handler(int sig){

    pid_t pid;
    int stat;

    while((pid = waitpid(-1,&stat,WNOHANG))>0){
        printf("child %d terminated\n",pid);
    }
    return;
}

int get_local_ip(const char *eth_inf,char *ipBuf)
{
    int sd;
    struct sockaddr_in sin;
    struct ifreq ifr;
 
    sd = socket(AF_INET, SOCK_DGRAM, 0);
    if (-1 == sd)
    {
        printf("socket error: %s\n", strerror(errno));
        return -1;
    }
 
    strncpy(ifr.ifr_name, eth_inf, IFNAMSIZ);
    ifr.ifr_name[IFNAMSIZ - 1] = 0;
 
    // if error: No such device  
    if (ioctl(sd, SIOCGIFADDR, &ifr) < 0)
    {
        printf("ioctl error: %s\n", strerror(errno));
        close(sd);
        return -1;
    }
    
    snprintf(ipBuf ,50,"%s" ,inet_ntoa(((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr)); 

    close(sd);
    return 0;
}


int main(int argc,char **argv){

    int listenfd,connfd,port,clientlen;
    struct sockaddr_in clientaddr;
    struct hostent *hp;
    char *haddrp;
    char sbuf[MAXLINE];
    char rbuf[MAXLINE];
    char myhost[32] = "";
    rio_t rio;
    time_t lt;
    tm *local;
    char str1[MAXLINE]="Server IP:";
    char str2[MAXLINE]="Server Implementer:";
    char str3[MAXLINE]="Current Time:";
     
    

    if(argc != 2){
    
        fprintf(stderr,"usage:%s <port>\n",argv[0]);
        exit(0);
    }

    port = atoi(argv[1]);

    signal(SIGCHLD,sigchld_handler);
    listenfd = open_listenfd(port);
    while(1){
    
        clientlen = sizeof(clientaddr);
        connfd = accept(listenfd,(SA *)&clientaddr,&clientlen);

        hp = gethostbyaddr((const char*)&clientaddr.sin_addr.s_addr,
                sizeof(clientaddr.sin_addr.s_addr),AF_INET);
        haddrp = inet_ntoa(clientaddr.sin_addr);
        printf("server connected to %s (%s)\n",hp->h_name,haddrp);

        if(fork() == 0){
        close(listenfd);
        lt = time(NULL); 
        local = localtime(&lt);
        strftime(sbuf,64,"%Y-%m-%d %H:%M:%S",local);
	get_local_ip("enp0s3",myhost);
	//send(connfd,myhost,MAXLINE,0);
	strcat(sbuf,"\n");
	strcat(sbuf,str1);
	strcat(sbuf,myhost);
        send(connfd,sbuf,MAXLINE,0);
        close(connfd);
        exit(0);
        }

        close(connfd);
    }
}

然后运行时就发生了非常神奇的事

在组(openeuler - kali)程序执行成功

在组(openeuler - ubuntu)程序执行失败

由此可见 不同操作系统对于内存管理的策略有所不同,安全性也有所不同。

类Unix操作系统对比

  • centos作为服务器部署是第一选择。CentOS去除很多与服务器功能无关的应用,系统简单但非常稳定,命令行操作可以方便管理系统和应用,丰富的帮助文档和社区的支持。

  • ubuntu最佳的应用领域是桌面操作系统而非服务器操作系统。

  • Debian作为服务器的选择,但是由于其发展路线,使它的帮助文档相对于CentOS略少,技术资料也少。

三大linux系统 内存安全 比较

暂时没有找到linux内存安全的相关资料 D:

但根据我以上实践的结果推测,可能是系统内核版本的原因,linux操作系统同出一源,区别不大,真正造成该现象的原因应该是内存管理策略的细微不同,也可能跟当时的系统状态有关。

posted @ 2021-12-11 21:38  20191331liyu  阅读(66)  评论(0编辑  收藏  举报