Windows에서 리눅스의 Shared Memory와 유사한 구조는 메모리 맵 파일 (Memory-Mapped File) 입니다.

메모리 맵 파일은 두 프로세스 간의 데이터 공유를 위해 사용할 수 있으며, 파일의 내용을 메모리에 매핑하여 프로세스가 이를 공유하게끔 합니다. 이는 리눅스의 shm_open()와 mmap() 함수로 메모리를 공유하는 방식과 유사합니다. Windows에서는 CreateFileMapping()과 MapViewOfFile() 함수를 사용하여 메모리 맵 파일을 생성하고, 이를 통해 메모리에 데이터를 매핑하여 여러 프로세스 간에 공유할 수 있습니다.

이 방식을 사용하면 각 프로세스가 같은 메모리 영역을 볼 수 있어 효율적으로 데이터를 교환할 수 있으며, 주로 큰 데이터 집합을 공유하거나 IPC(Inter-Process Communication)를 구현할 때 사용됩니다.

struct  KSEJONG_MEMREC     {
Ubyte lock_flag; /* 메모리사용상태 */
Ubyte seq[4];
Ubyte seq_no[4];
Ubyte   full_code[12];
Ubyte   code[7];
Ubyte jmast[SZ_JMAST +1];
Ubyte jsise[SZ_JSISE +1];
Ubyte info[SZ_INFO  +1];
Ubyte hando[SZ_HANDO +1];
Ubyte chegyul_cnt[2];
Ubyte danilsise[SZ_DANILSISE+1];
Ubyte   danilchegyul[CNT_DANILCHEGYUL][SZ_TIMECHEGYUL + 1];
};
#define SZ_KSEJONG_MEMREC  sizeof(struct   KSEJONG_MEMREC)
#define OFF_KSESHM (SZ_KSEJONG_MEMREC * CNT_KSEJONG)

Windows에서 C 언어로 KSEJONG_MEMREC 구조체를 메모리 맵 파일을 통해 공유하는 예제를 구성해보겠습니다. 아래 코드는 KSEJONG_MEMREC 구조체를 정의하고, 메모리 맵 파일을 통해 데이터를 공유하는 예제입니다. 한 프로그램에서 데이터를 쓰고, 다른 프로그램에서 이를 읽을 수 있도록 작성하였습니다.

1. 구조체 정의 및 메모리 맵 파일에 쓰기

먼저, 메모리 맵 파일에 데이터를 쓰는 코드를 작성하겠습니다.

#include <windows.h>
#include <stdio.h>
#include <string.h>

#define SZ_JMAST 20
#define SZ_JSISE 20
#define SZ_INFO 20
#define SZ_HANDO 20
#define SZ_DANILSISE 20
#define CNT_DANILCHEGYUL 5
#define SZ_TIMECHEGYUL 20
#define CNT_KSEJONG 10

// KSEJONG_MEMREC 구조체 정의
#pragma pack(push, 1)
typedef struct {
    BYTE lock_flag;                 // 메모리 사용 상태
    BYTE seq[4];                    // 주소
    BYTE seq_no[4];                 // 신코드Seq
    BYTE full_code[12];             // 풀코드
    BYTE code[7];                   // 단축코드
    BYTE jmast[SZ_JMAST + 1];       // 거래소 종목마스터
    BYTE jsise[SZ_JSISE + 1];       // 거래소 종목시세
    BYTE info[SZ_INFO + 1];         // 거래소 거래원정보
    BYTE hando[SZ_HANDO + 1];       // 거래소 외국인한도
    BYTE chegyul_cnt[2];            // 체결 갯수
    BYTE danilsise[SZ_DANILSISE + 1]; // 시세
    BYTE danilchegyul[CNT_DANILCHEGYUL][SZ_TIMECHEGYUL + 1]; // 체결
} KSEJONG_MEMREC;
#pragma pack(pop)

#define MEM_SIZE (sizeof(KSEJONG_MEMREC) * CNT_KSEJONG)

int main()
{
    // 메모리 맵 파일 생성
    HANDLE hMapFile = CreateFileMapping(
        INVALID_HANDLE_VALUE,
        NULL,
        PAGE_READWRITE,
        0,
        MEM_SIZE,
        TEXT("KSEJONG_SharedMemory"));

    if (hMapFile == NULL) {
        printf("Could not create file mapping object (%d).\n", GetLastError());
        return 1;
    }

    // 메모리 맵 파일에 대한 뷰 생성
    KSEJONG_MEMREC* pBuf = (KSEJONG_MEMREC*) MapViewOfFile(
        hMapFile,
        FILE_MAP_ALL_ACCESS,
        0,
        0,
        MEM_SIZE);

    if (pBuf == NULL) {
        printf("Could not map view of file (%d).\n", GetLastError());
        CloseHandle(hMapFile);
        return 1;
    }

    // 데이터 초기화 및 쓰기
    memset(pBuf, 0, sizeof(KSEJONG_MEMREC));
    pBuf->lock_flag = 1;
    memcpy(pBuf->seq, "1234", 4);
    memcpy(pBuf->seq_no, "5678", 4);
    memcpy(pBuf->full_code, "FULLCODE1234", 12);
    memcpy(pBuf->code, "CODE123", 7);
    memcpy(pBuf->jmast, "MasterInfo", 10);
    memcpy(pBuf->jsise, "PriceInfo", 9);
    memcpy(pBuf->info, "TradeInfo", 9);
    memcpy(pBuf->hando, "HandoInfo", 9);
    pBuf->chegyul_cnt[0] = 1;
    pBuf->chegyul_cnt[1] = 2;
    memcpy(pBuf->danilsise, "PriceData", 9);
    memcpy(pBuf->danilchegyul[0], "TradeData1", 10);

    printf("Data written to shared memory.\n");

    // 메모리 뷰 및 핸들 닫기
    UnmapViewOfFile(pBuf);
    CloseHandle(hMapFile);

    return 0;
}

2. 메모리 맵 파일에서 데이터 읽기

다음은 메모리 맵 파일에 저장된 데이터를 읽는 코드입니다.

#include <windows.h>
#include <stdio.h>

#define SZ_JMAST 20
#define SZ_JSISE 20
#define SZ_INFO 20
#define SZ_HANDO 20
#define SZ_DANILSISE 20
#define CNT_DANILCHEGYUL 5
#define SZ_TIMECHEGYUL 20
#define CNT_KSEJONG 10

#pragma pack(push, 1)
typedef struct {
    BYTE lock_flag;
    BYTE seq[4];
    BYTE seq_no[4];
    BYTE full_code[12];
    BYTE code[7];
    BYTE jmast[SZ_JMAST + 1];
    BYTE jsise[SZ_JSISE + 1];
    BYTE info[SZ_INFO + 1];
    BYTE hando[SZ_HANDO + 1];
    BYTE chegyul_cnt[2];
    BYTE danilsise[SZ_DANILSISE + 1];
    BYTE danilchegyul[CNT_DANILCHEGYUL][SZ_TIMECHEGYUL + 1];
} KSEJONG_MEMREC;
#pragma pack(pop)

#define MEM_SIZE (sizeof(KSEJONG_MEMREC) * CNT_KSEJONG)

int main()
{
    // 기존 메모리 맵 파일 열기
    HANDLE hMapFile = OpenFileMapping(
        FILE_MAP_ALL_ACCESS,
        FALSE,
        TEXT("KSEJONG_SharedMemory"));

    if (hMapFile == NULL) {
        printf("Could not open file mapping object (%d).\n", GetLastError());
        return 1;
    }

    // 메모리 맵 파일에 대한 뷰 생성
    KSEJONG_MEMREC* pBuf = (KSEJONG_MEMREC*) MapViewOfFile(
        hMapFile,
        FILE_MAP_ALL_ACCESS,
        0,
        0,
        MEM_SIZE);

    if (pBuf == NULL) {
        printf("Could not map view of file (%d).\n", GetLastError());
        CloseHandle(hMapFile);
        return 1;
    }

    // 데이터 읽기
    printf("Read from shared memory:\n");
    printf("Lock Flag: %d\n", pBuf->lock_flag);
    printf("Seq: %.4s\n", pBuf->seq);
    printf("Seq No: %.4s\n", pBuf->seq_no);
    printf("Full Code: %.12s\n", pBuf->full_code);
    printf("Code: %.7s\n", pBuf->code);
    printf("Jmast: %.10s\n", pBuf->jmast);
    printf("Jsise: %.9s\n", pBuf->jsise);
    printf("Info: %.9s\n", pBuf->info);
    printf("Hando: %.9s\n", pBuf->hando);
    printf("Chegyul Cnt: %d %d\n", pBuf->chegyul_cnt[0], pBuf->chegyul_cnt[1]);
    printf("Danilsise: %.9s\n", pBuf->danilsise);
    printf("Danilchegyul[0]: %.10s\n", pBuf->danilchegyul[0]);

    // 메모리 뷰 및 핸들 닫기
    UnmapViewOfFile(pBuf);
    CloseHandle(hMapFile);

    return 0;
}

설명

  1. 쓰기 코드는 CreateFileMapping으로 메모리 맵 파일을 생성하고 MapViewOfFile로 메모리 뷰를 얻습니다. 이후 구조체 데이터를 메모리에 씁니다.
  2. 읽기 코드는 OpenFileMapping을 통해 기존 메모리 맵 파일에 접근하고, MapViewOfFile로 메모리 뷰를 얻어 데이터를 읽어옵니다.

이 코드를 통해 Windows 환경에서 C 언어로 Shared Memory를 사용할 수 있습니다.

이 코드는 Windows API 함수(CreateFileMapping, MapViewOfFile, UnmapViewOfFile, CloseHandle 등)를 사용하기 때문에 추가적인 라이브러리 링크는 필요하지 않습니다. Windows API는 기본적으로 Windows 운영 체제에 포함되어 있으므로 별도의 라이브러리를 링크하지 않아도 됩니다.

Visual Studio와 GCC(MinGW) 모두 Windows API 함수가 기본적으로 포함되어 있어서, 별도의 라이브러리 옵션을 명시하지 않고도 컴파일할 수 있습니다.

gcc write_memory.c -o write_memory.exe
gcc read_memory.c -o read_memory.exe

아래 명령을 사용하여 모든 .cs 파일에서 아스키 코드 123 ({)을 제거할 수 있습니다.

find 명령으로 찾은 .cs 파일들에서 아스키 코드 123 ({, 즉 16진수로는 7B)를 제거하려면, 다음과 같은 방법을 사용할 수 있습니다.

sed 사용)

아래 명령을 사용하여 모든 .cs 파일에서 아스키 코드 123 ({)을 제거할 수 있습니다.

find ./ -name "*.cs" -exec sed -i 's/\%x7B//g' {} +

비고) 문장전체를 바꿀때에
1)AddItemToList("QCS:" + queueName, jsonText);
2)AddItemToList("QCS:" + APMMemory.GetInstance.redisSenderQueueNM, jsonString);

find ./ -name "*.cs" -exec sed -i 's/AddItemToList("QCS:" + queueName, jsonText)/AddItemToList("QCS:" + APMMemory.GetInstance.redisSenderQueueNM, jsonString)/g' {} \;

현재 Text파일의 인코딩형식을 알려면)
B210145_BK@DESKTOP-QNNUCER MINGW64 ~/Downloads/NodeServer/redis_web_5_5_ticker/multiloginredistickserver
$ find ./ -name "*.cs" -exec file -i {} \;
./APMMemory.cs: text/x-c++; charset=utf-8
./APMSQLite.cs: text/x-c++; charset=us-ascii
./DataEncoding.cs: text/x-c++; charset=utf-8
./ExturePlusElw.cs: text/x-c++; charset=utf-8
./ExturePlusElwText.cs: text/x-c++; charset=utf-8
./ExturePlusFuture.cs: text/x-c++; charset=utf-8
./ExturePlusFutureText.cs: text/x-c++; charset=utf-8
./ExturePlusKosdaq.cs: text/x-c++; charset=utf-8
./ExturePlusKosdaqQuote10.cs: text/x-c++; charset=utf-8

인코딩변경)
./ExturePlusElwText.cs: text/x-c++; charset=utf-8
./ExturePlusFuture.cs: text/x-c++; charset=utf-8
./ExturePlusFutureText.cs: text/x-c++; charset=iso-8859-1
./ExturePlusFutureTextText.cs: text/x-c++; charset=iso-8859-1
./ExturePlusKosdaq.cs: text/x-c++; charset=utf-8
./ExturePlusKosdaqQuote10.cs: text/x-c++; charset=utf-8


find ./ -name "*.cs" -exec iconv -f utf-8 -t iso-8859-1 {} -o {}.tmp \; -exec mv {}.tmp {} \;

Redis는 클라이언트의 연결 수를 제한하는 기능을 제공합니다. 이를 통해 Redis 서버가 과도한 연결로 인해 리소스가 소모되는 것을 방지할 수 있습니다. 기본적으로 Redis는 클라이언트 연결 수에 대한 제한을 설정하지 않지만, 몇 가지 방법으로 이를 조정할 수 있습니다:

  1. maxclients 설정: Redis의 설정 파일(redis.conf)에서 maxclients 옵션을 사용하여 허용할 최대 클라이언트 연결 수를 설정할 수 있습니다. 예를 들어, maxclients 10000이라고 설정하면 최대 10,000개의 클라이언트가 동시에 연결될 수 있습니다. 이 값은 Redis 서버의 메모리와 시스템의 자원에 따라 조정해야 합니다.
  2.  
    maxclients 10000
  3. 운영 체제의 파일 핸들 제한: Redis는 운영 체제의 파일 핸들 수에 따라 제한을 받을 수 있습니다. Redis는 각 클라이언트 연결을 파일 핸들로 처리하므로, 운영 체제에서 허용하는 파일 핸들의 수에 따라 Redis의 최대 연결 수가 제한될 수 있습니다. 이를 조정하려면 운영 체제의 설정을 변경해야 합니다. 예를 들어, Linux에서는 ulimit 명령어를 사용하여 파일 핸들 수를 조정할 수 있습니다.
  4.  
    ulimit -n 10000
  5. 클라이언트 연결 수의 모니터링: Redis 서버의 연결 상태를 모니터링하는 것도 중요합니다. INFO clients 명령어를 사용하여 현재 연결된 클라이언트의 수를 확인할 수 있습니다.
  6.  
    INFO clients
  7. client-output-buffer-limit 설정: Redis는 클라이언트의 출력 버퍼가 너무 커지는 것을 방지하기 위해 client-output-buffer-limit 설정을 제공합니다. 이 설정은 클라이언트가 보내는 데이터의 크기를 제한하여 서버가 과도한 메모리를 소비하지 않도록 합니다.
  8.  
    client-output-buffer-limit pubsub 33554432 8388608 60

Redis 서버의 연결 제한을 적절히 설정하면 성능을 안정적으로 유지할 수 있으며, 시스템 자원을 효율적으로 관리할 수 있습니다.

Linux에서 C# 프로젝트를 설정하고 빌드하는 과정은 다음과 같습니다. 이 과정에서는 .NET Core 또는 .NET 5/6/7 SDK를 사용하여 C# 프로젝트를 설정하고 빌드합니다. 이 가이드는 Ubuntu 시스템을 기준으로 작성되었습니다.

1. .NET SDK 설치

패키지 목록 업데이트 및 필수 패키지 설치
sudo apt update
sudo apt install -y wget apt-transport-https software-properties-common
wget https://packages.microsoft.com/keys/microsoft.asc
sudo apt-key add microsoft.asc
sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/ubuntu/20.04/prod focal main" > /etc/apt/sources.list.d/dotnetdev.list'

.NET SDK 설치
sudo apt update
sudo apt install -y dotnet-sdk-7.0

설치 확인
dotnet --version

2. C# 프로젝트 생성
> dotnet new console -o mdiwebrowser

비고)
WPF 프로젝트 생성(다음 명령어로 WPF 프로젝트를 생성합니다.)
> dotnet new wpf -o <프로젝트이름>


프로젝트 디렉토리로 이동

프로젝트 빌드 및 실행

프로젝트 빌드
dotnet build


dotnet add package Newtonsoft.Json
dotnet add package ServiceStack.Redis
dotnet add package System.Data.SQLite


프로젝트 실행
dotnet run

1. 특정 폴더 일괄 지우기(특정 폴더)

find . -name "test" -type d -exec rm -rf {} \;
or
find . -name "test*" -type d | xargs rm -rf

하위까지(APM),ㅡㅡㅡㅡㅡ
find ./ -name "obj" -type d | xargs rm -rf
find ./ -name "obj" -type d | xargs rm -rf
find ./ -name "obj" -type d | xargs rm -rf

2. 특정 파일 일괄 지우기

find . -name "test" -type f -exec rm -rf {} \;
or
find . -name "*test*" -type f | xargs rm -rf

한글꺠짐.언어설정) SAMSUNG.NOTE

한글안꺠짐.언어설정) DELL

sinfo@sinfo:/data/exture_3_0/20221026$ locale
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
sinfo@sinfo:/data/exture_3_0/20221026$

ftp 설치

>apt-get install vsftpd
>vim /etc/vsftpd.conf

chroot_list_enable=YES
chroot_list_file=/etc/vsftpd.chroot_list
allow_writeable_chroot=YES
write enable=YES

vsftpd.chroot_list 파일에 있는 “특정 사용자”에 대해서만 접근을 할 수 있도록 해주는 내용입니다.
해당 파일은 없기 때문에 파일을 생성해 원하시는 계정명을 1줄씩 입력하시면 됩니다.


service vsftpd restart
ufw allow 21/tcp

> Ubuntu 20.04 환경에서 Telnet을 설치하는 방법

$apt-get install xinetd telnetd
$vi /etc/xinetd.d/telnet

service telnet
{
disable = no
flags = REUSE
socket_type = stream
wait = no
user = root
server = /usr/sbin/in.telnetd
log_on_failure += USERID
}

$ sudo systemctl restart xinetd
$ sudo systemctl enable xinetd
$ sudo ufw allow 23/tcp

+ Recent posts