<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>zi_won</title>
        <link>https://velog.io/</link>
        <description>BSSM</description>
        <lastBuildDate>Mon, 04 Dec 2023 16:09:44 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>zi_won</title>
            <url>https://velog.velcdn.com/images/ziwon_c/profile/3ba43ba1-8bac-4876-82ce-7b1106abfc29/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. zi_won. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ziwon_c" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Linux] 파이프 개요 및 이름 없는 파이프]]></title>
            <link>https://velog.io/@ziwon_c/%ED%8C%8C%EC%9D%B4%ED%94%84-%EA%B0%9C%EC%9A%94-%EB%B0%8F-%EC%9D%B4%EB%A6%84-%EC%97%86%EB%8A%94-%ED%8C%8C%EC%9D%B4%ED%94%84</link>
            <guid>https://velog.io/@ziwon_c/%ED%8C%8C%EC%9D%B4%ED%94%84-%EA%B0%9C%EC%9A%94-%EB%B0%8F-%EC%9D%B4%EB%A6%84-%EC%97%86%EB%8A%94-%ED%8C%8C%EC%9D%B4%ED%94%84</guid>
            <pubDate>Mon, 04 Dec 2023 16:09:44 GMT</pubDate>
            <description><![CDATA[<h2 id="1-파이프-개요">1. 파이프 개요</h2>
<hr>
<p><img src="https://velog.velcdn.com/images/ziwon_c/post/255c1185-a0d6-48f4-a00e-2c88f9a0ac6d/image.png" alt=""></p>
<ul>
<li>물을 보내는 수도 파이프와 비슷</li>
<li>파이프는 두 프로세스 사이에서 한 방향으로 통신할 수 있도록 지원하는 것</li>
<li>한 프로세스는 쓰기용 파일 디스크립터를 이용하여 파이프에 데이터를 보내고</li>
<li>다른 프로세스는 읽기용 파일 디스크립터를 이용하여 그 파이프에서 데이터를 받음</li>
<li>한 방향(one way) 통신<pre><code>cat test.c | more_</code></pre></li>
<li>앞에 있는 명령인 cat test.c 의 표준 출력을 다음 명령인 more의 표준 입력으로 사용</li>
<li>파이프는 이름 없는 파이프와 이름 있는 파이프로 구분</li>
</ul>
<h3 id="이름-없는-파이프--pipe">이름 없는 파이프 : pipe</h3>
<ul>
<li>특별한 수식어 없이 그냥 파이프라고 하면 일반적으로 이름 없는 파이프(익명 파이프)를 의미</li>
<li>부모 - 자식 프로세스 간에 통신을 할 수 있게 해줌</li>
<li>부모 프로세스에서 fork() 함수를 통해 자식 프로세스를 생성, 부모 프로세스와 자식 프로세스 간에 통신하는 것</li>
</ul>
<h4 id="이름-없는-파이프-생성-함수">이름 없는 파이프 생성 함수</h4>
<h5 id="간단한-파이프-생성">간단한 파이프 생성</h5>
<pre><code>FILE *popen(const char *command, const char *type);</code></pre><pre><code>int pclose(FILE *stream);</code></pre><h5 id="복잡한-파이프-생성">복잡한 파이프 생성</h5>
<pre><code>int pipe(int pipefd[2]);</code></pre><h3 id="이름-있는-파이프--fifo">이름 있는 파이프 : FIFO</h3>
<ul>
<li>특수 파일의 한 종류</li>
<li>모든 프로세스가 이름 있는 파이프를 이용해 통신할 수 있음<h4 id="이름-있는-파이프-생성-명령과-함수">이름 있는 파이프 생성 명령과 함수</h4>
<h5 id="fifo-생성-명령">FIFO 생성 명령</h5>
<pre><code>mknod 파일명 p</code></pre><pre><code>mkfifo [-m mode] ...NAME...</code></pre><h5 id="fifo-생성-함수">FIFO 생성 함수</h5>
<pre><code>int mknod(const char *pathname, mode_t mode, dev_t dev);</code></pre><pre><code>int mkfifo(const char *pathname, mode_t mode);</code></pre></li>
</ul>
<h2 id="2-이름-없는-파이프">2. 이름 없는 파이프</h2>
<hr>
<ul>
<li>파이프는 두 프로세스 간에 통신을 할 수 있도록 인터페이스를 제공</li>
<li>수식어가 없는 파이프, 즉 이름 없는 파이프는 부모 - 자식 프로세스 간에 통신을 할 수 있게 함</li>
<li>파이프는 기본적으로 단방향</li>
<li>따라서 부모 프로세스가 출력한 내용을 자식 프로세스에서 읽을 것인지, 자식 프로세스가 출력한 내용을 부모 프로세스에서 읽을 것인지 둘 중 한 방향을 선택</li>
<li>이는 수도관에 물을 보낼 때 양쪽에서 서로 보낼 수 없는 이치와 마찬가지임</li>
</ul>
<h3 id="21-간단한-파이프-생성">2.1 간단한 파이프 생성</h3>
<p>파이프를 만드는 가장 간단한 방법은 popen() 함수를 사용하는 것</p>
<h4 id="파이프-만들기--popen3">파이프 만들기 : popen(3)</h4>
<pre><code>#include&lt;stdio.h&gt;

FILE *popen(const char *command, const char *type);

* command : 셀 명령
* type : &quot;r&quot; 또는 &quot;w&quot;</code></pre><ul>
<li>popen() 함수는 다른 프로세스와 통신하기 위해 파이프를 생성</li>
<li>command에는 셀 명령을, 두 번째 인자인 type에는 &quot;r&quot;이나 &quot;w&quot;를 지정</li>
<li>&quot;r&quot;를 읽기 전용으로, &quot;w&quot;는 쓰기 전용으로 엶<pre><code>execl(&quot;/bin/sh&quot;, &quot;sh&quot;, &quot;-c&quot;, command, (char *)0);</code></pre></li>
<li>popen() 함수는 자식 프로세스와 파이프를 만들고 mode의 값에 따라 표준 입출력을 연결함</li>
<li>리턴 값은 파일 포인터</li>
<li>파일 입출력 함수에서 이 파일 포인터를 사용하면 파이프를 읽거나 쓸 수 있음</li>
<li>popen() 함수는 파이프 생성에 실패하면 널 포인터를 반환</li>
</ul>
<h4 id="파이프-닫기--pclose">파이프 닫기 : pclose</h4>
<pre><code>#include&lt;stdio.h&gt;

int pclose(FILE *stream);

* stream : popen 함수에서 리턴한 파일 포인터
* return : 자식 프로세스의 종료 상태(exit status) / 실패 시 -1</code></pre><p><em>popen() 함수를 쓰기 전용 모드로 사용해 파이프를 생성해보자</em></p>
<pre><code>#include&lt;stdlib.h&gt;
#include&lt;stdio.h&gt;

int main() {
    FILE *fp;
    int a;

    fp = popen(&quot;wc -l&quot;, &quot;w&quot;);
    if (fp == NULL) {
    fprintf(stderr, &quot;popen failed\n&quot;);
    exit(1);
    }

    for (a = 0; a &lt; 100; a++)
        fprintf(fp, &quot;test line\n&quot;);

    pclose(fp);
}
</code></pre><pre><code>결과 값 : 100</code></pre><ul>
<li><strong>08행</strong> &quot;w&quot; 모드를 사용해 쓰기 전용 파이프를 생성하고 자식 프로세스는 wc -l 명령을 수행하도록 함. wc -l은 입력되는 데이터의 데이터의 행 수를 출력하는 명령</li>
<li><strong>14~15행</strong> 부모 프로세스에서는 반복문을 사용해 문자열을 파이프로 출력함. 앞서 언급했듯 이 자식 프로세스는 파이프로 입력되는 문자열을 읽어서 wc -l 명령을 수행함.</li>
</ul>
<p><em>이번에는 popen() 함수를 읽기 전용 모드로 사용해 파이프를 생성해보자. 자식 프로세스가 파이프에 기록한 데이터를 부모 프로세스가 읽어서 처리한다.</em></p>
<pre><code>#include&lt;stdlib.h&gt;
#include&lt;stdio.h&gt;

int main() {
    FILE *fp;
    char buf[256];

    fp = popen(&quot;date&quot;, &quot;r&quot;);
    if(fp == NULL) {
        fprintf(stderr, &quot;popen failed\n&quot;);
        exit(1);
   }
   if (fgets(buf, sizeof(buf), fp) == NULL) {
           fprintf(stderr, &quot;No data from pipe!\n&quot;);
        exit(1);
   }

   printf(&quot;line : %s\n&quot;, buf);
   pclose(fp);
}</code></pre><pre><code>결과 값 : line : 현재 날짜 및 시간 정보</code></pre><ul>
<li><strong>08행</strong> 자식 프로세스에서는 date 명령을 수행함</li>
<li><strong>14행, 19행</strong> 부모 프로세스에서는 자식 프로세스가 기록한 데이터를 14행에서 읽고 저장해 19행에서 출력함</li>
<li><strong>실행 결과</strong> 현재 날짜와 시각이 출력되었음. 자식 프로세스가 실행한 date 명령의 결과를 부모 프로세스가 읽어서 출력한 것</li>
</ul>
<h3 id="22-복잡한-파이프-생성">2.2 복잡한 파이프 생성</h3>
<ul>
<li>popen() 함수를 사용해 파이프를 생성하는 일은 간단, 셸을 실행해야 하므로 비효율적이고 주고받을 수 있는 데이터도 제한적</li>
<li>popen() 함수 대신 pipe() 함수를 사용하면 과정은 복잡해지지만 파이프를 좀 더 효율적으로 생성 가능</li>
</ul>
<h4 id="파이프-만들기--pipe2">파이프 만들기 : pipe(2)</h4>
<pre><code>#include&lt;unistd.h&gt;

int pipe(int pipefd[2]);</code></pre><ul>
<li>인자 설명
pipefd[2] : 파이프로 사용할 파일 기술자(2개)</li>
</ul>
<ul>
<li>pipe() 함수는 인자로 크기가 2인 정수형 배열을 받음</li>
<li>pipe() 함수는 이 배열에 파일 기술자 2개를 저장함</li>
<li>pipefd[0]은 읽기 전용으로 열고 pipefd[1]은 쓰기 전용으로 엶</li>
<li>pipe() 함수는 파이프를 생성하는 데 성공하면 0을, 실패하면 -1을 리턴함</li>
</ul>
<h4 id="pipe-함수로-통신하는-과정">pipe() 함수로 통신하는 과정</h4>
<p><em>pipe() 함수로 생성한 파이프로 통신하는 과정을 살펴보자</em></p>
<ul>
<li>파이프를 생성하면 일반적으로 fork() 함수를 호출해 자식 프로세스를 생성함</li>
<li>자식 프로세스는 부모 프로세스가 pipe() 함수로 생성한 파일 기술자도 복사함</li>
<li>이 파이프를 이용해 한 프로세스에서는 쓰기를 수행하고 다른 프로세스에서는 읽기를 수행하면 통신이 됨</li>
</ul>
<p><em>이 과정을 단계적으로 살펴보자</em>
<strong>1.</strong> pipe() 함수를 호출해 파이프에 사용할 파일 기술자를 얻음. 파이프도 파일의 일종이므로 파일(파이프)을 읽고 쓸 수 있는 파일 기술자가 필요한데, 이를 pipe() 함수가 생성해줌.</p>
<p><strong>2.</strong> fork() 함수를 수행해 자식 프로세스를 생성함. 이때 pipe() 함수에서 생성한 파일 기술자도 자식 프로세스로 복사됨. 같은 파일 기술자를 부모 프로세스와 자식 프로세스가 모두 가지고 있음</p>
<p><strong>3.</strong> 파이프는 단방향 통신이므로 통신 방향을 결정함. 예를 들어, 부모 프로세스는 쓰기를 하고 자식 프로세스는 읽기를 해야한다고 했을 때, 각각의 파일 기술자에서 쓰지 않는 읽기 또는 쓰기의 파일 기술자를 닫아야 함</p>
<p>만약! 파이프의 쓰기 부분이 닫혀 있다면 파이프에서 읽으려고 할 때 0이나 EOF가 리턴함
파이프의 읽기 부분이 닫혀 있다면 파이프에 쓰려고 할 때 SIGPIPE 시그널이 발생함</p>
<h5 id="부모-프로세스와-자식-프로세스-사이에서-파이프를-사용하여-통신하는-예제">부모 프로세스와 자식 프로세스 사이에서 파이프를 사용하여 통신하는 예제</h5>
<pre><code>#include &lt;sys/wait.h&gt;
#include &lt;unistd.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;

int main() {
    int fd[2]; // 파이프 파일 디스크립터를 저장할 배열
    pid_t pid; // 프로세스 ID를 저장할 변수
    char buf[257]; // 메시지를 저장할 버퍼
    int len, status;

    // 파이프 생성
    if (pipe(fd) == -1) {
        perror(&quot;pipe&quot;); // 에러 메시지 출력
        exit(1); // 프로그램 종료
    }

    // 자식 프로세스 생성
    switch (pid = fork()) {
        case -1 : // fork 실패 시
            perror(&quot;fork&quot;); // 에러 메시지 출력
            exit(1); // 프로그램 종료
            break;
        case 0 : /* 자식 프로세스 */
            close(fd[1]); // 쓰기용 파이프 종료
            write(1, &quot;Child Process:&quot;, 15); // 자식 프로세스 메시지 출력
            len = read(fd[0], buf, 256); // 읽기용 파이프에서 메시지 읽기
            write(1, buf, len); // 읽은 메시지 출력
            close(fd[0]); // 읽기용 파이프 종료
            break;
        default : /* 부모 프로세스 */
            close(fd[0]); // 읽기용 파이프 종료
            write(fd[1], &quot;Test Message\n&quot;, 14); // 쓰기용 파이프에 메시지 쓰기
            close(fd[1]); // 쓰기용 파이프 종료
            waitpid(pid, &amp;status, 0); // 자식 프로세스가 종료될 때까지 대기
            break;
    }
}
</code></pre><pre><code>결과 값 : Child Process: Test Message</code></pre><h5 id="부모-프로세스가-ps--ef명령을-실행한-뒤-그-결과를-자식-프로세스로-전달-자식-프로세스는-그-결과-중-ssh를-포함한-라인만-필터링하여-출력하는-예제">부모 프로세스가 ps -ef명령을 실행한 뒤 그 결과를 자식 프로세스로 전달, 자식 프로세스는 그 결과 중 &quot;ssh&quot;를 포함한 라인만 필터링하여 출력하는 예제</h5>
<pre><code>#include &lt;sys/wait.h&gt;
#include &lt;unistd.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;

int main() {
    int fd[2]; // 파이프 파일 디스크립터를 저장할 배열
    pid_t pid; // 프로세스 ID를 저장할 변수

    // 파이프 생성
    if (pipe(fd) == -1) {
        perror(&quot;pipe&quot;); // 에러 메시지 출력
        exit(1); // 프로그램 종료
    }

    // 자식 프로세스 생성
    switch (pid = fork()) {
        case -1 : // fork 실패 시
            perror(&quot;fork&quot;); // 에러 메시지 출력
            exit(1); // 프로그램 종료
            break;
        case 0 : /* 자식 프로세스 */
            close(fd[1]); // 쓰기용 파이프 종료
            if (fd[0] != 0) {
                dup2(fd[0], 0); // 읽기용 파이프를 표준 입력으로 복제
                close(fd[0]); // 복제된 읽기용 파이프 종료
            }
            execlp(&quot;grep&quot;, &quot;grep&quot;, &quot;ssh&quot;, (char *)NULL); // &quot;ssh&quot;를 포함한 라인만 필터링하는 grep 명령 실행
            exit(1); // 프로그램 종료
            break;
        default : /* 부모 프로세스 */
            close(fd[0]); // 읽기용 파이프 종료
            if (fd[1] != 1) {
                dup2(fd[1], 1); // 쓰기용 파이프를 표준 출력으로 복제
                close(fd[1]); // 복제된 쓰기용 파이프 종료
            }
            execlp(&quot;ps&quot;, &quot;ps&quot;, &quot;-ef&quot;, (char *)NULL); // 모든 프로세스의 정보를 출력하는 ps 명령 실행
            wait(NULL); // 자식 프로세스가 종료될 때까지 대기
            break;
    }
}
</code></pre><h3 id="양방향-파이프의-활용">양방향 파이프의 활용</h3>
<ul>
<li>파이프는 기본적으로 단방향 통신을 수행함</li>
<li>따라서 양방향 통신을 하려면 파이프를 두 개 생성하면 됨</li>
<li>상수도와 하수도가 각각 별도의 파이프로 구성되어 있는 것과 같은 이치임<h5 id="부모-프로세스와-자식-프로세스가-양방향으로-통신하는-예제">부모 프로세스와 자식 프로세스가 양방향으로 통신하는 예제</h5>
<pre><code>#include &lt;sys/wait.h&gt;
#include &lt;unistd.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
</code></pre></li>
</ul>
<p>int main() {
    int fd1[2], fd2[2]; // 양방향 통신을 위한 두 개의 파이프 파일 디스크립터 배열
    pid_t pid; // 프로세스 ID를 저장할 변수
    char buf[257]; // 메시지를 저장할 버퍼
    int len, status;</p>
<pre><code>// 첫 번째 파이프 생성
if (pipe(fd1) == -1) {
    perror(&quot;pipe&quot;); // 에러 메시지 출력
    exit(1); // 프로그램 종료
}

// 두 번째 파이프 생성
if (pipe(fd2) == -1) {
    perror(&quot;pipe&quot;); // 에러 메시지 출력
    exit(1); // 프로그램 종료
}

// 자식 프로세스 생성
switch (pid = fork()) {
    case -1 : // fork 실패 시
        perror(&quot;fork&quot;); // 에러 메시지 출력
        exit(1); // 프로그램 종료
        break;
    case 0 : /* 자식 프로세스 */
        close(fd1[1]); // 첫 번째 파이프의 쓰기용 종료
        close(fd2[0]); // 두 번째 파이프의 읽기용 종료
        len = read(fd1[0], buf, 256); // 첫 번째 파이프에서 메시지 읽기
        write(1, &quot;Child Process:&quot;, 15); // 자식 프로세스 메시지 출력
        write(1, buf, len); // 읽은 메시지 출력

        strcpy(buf, &quot;Good\n&quot;); // 버퍼에 &quot;Good\n&quot; 문자열 복사
        write(fd2[1], buf, strlen(buf)); // 두 번째 파이프에 메시지 쓰기
        break;
    default : /* 부모 프로세스 */
        close(fd1[0]); // 첫 번째 파이프의 읽기용 종료
        close(fd2[1]); // 두 번째 파이프의 쓰기용 종료
        write(fd1[1], &quot;Hello\n&quot;, 6); // 첫 번째 파이프에 메시지 쓰기

        len = read(fd2[0], buf, 256); // 두 번째 파이프에서 메시지 읽기
        write(1, &quot;Parent Process:&quot;, 15); // 부모 프로세스 메시지 출력
        write(1, buf, len); // 읽은 메시지 출력
        waitpid(pid, &amp;status, 0); // 자식 프로세스가 종료될 때까지 대기
        break;
}</code></pre><p>}</p>
<pre><code></code></pre><p>결과 값 : username   1234  0.0  0.0   1234   5678 pts/0    Ss+  Dec04   0:00 ssh <a href="mailto:example@example.com">example@example.com</a></p>
<p>```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQLD 기출 문제 풀이]]></title>
            <link>https://velog.io/@ziwon_c/SQLD-%EA%B8%B0%EC%B6%9C-%EB%AC%B8%EC%A0%9C-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@ziwon_c/SQLD-%EA%B8%B0%EC%B6%9C-%EB%AC%B8%EC%A0%9C-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Tue, 09 May 2023 05:48:15 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/a78769a3-c669-41d0-9900-2c570454fcf5/image.png" alt=""></p>
<h1 id="20230509">2023.05.09</h1>
<p>1) 수직 분할 : 특정 칼럼 단위로 테이블을 분할, 디스크 I/O을 줄일 수 있는 방법
2) 정규화</p>
<ul>
<li>제 1 정규화 : 테이블의 속성 하나는 하나의 속성 값만을 가져야 한다.</li>
<li>제 2 정규화 : 종속된 컬럼이 존재할 경우 테이블을 분해한다.</li>
<li>제 3 정규화 : 제 2 정규화을 만족하는 상태
에서 이행 함수 종속을 제거한다.
3) SINGLE TYPE : 하나의 테이블로 통합해서 만드는 방법
4) 엔터티의 종류</li>
<li>독립 엔티티 : 현실세계에 존재하는 엔터티 ex. 사람, 물건, 장소</li>
<li>업무 중심 엔터티 : Transaction이 실행되면서 발생하는 엔터티</li>
<li>종속 엔터티 : 1차 정규화로 인해 관련 중심 엔티티로부터 분리된 엔터티</li>
<li>교차 엔티티 : M:N의 관계를 해소하려는 목적으로 만들어진 엔터티</li>
</ul>
<ol>
<li>유형과 무형으로 구분하는 기준은 물리적 형태의 존재 여부
유형 엔티티 : 업무에서 도출되며 지속적으로 사용
개념 엔터티 : 개념적으로 사용되는 엔터티
사건 엔터티 : 비즈니스 프로세스를 실행하면서 생성되는 엔터티</li>
<li>발생 시점에 따른 엔터티 종류
기본 엔터티 : 다른 엔터티로부터 영향을 받지 않고 독립적으로 생성되는 엔터티
중심 엔터티 : 기본 엔터티와 행위 엔터티 간의 중간에 있는 엔터티
행위 엔터티 : 2개 이상의 엔터티로부터 발생하는 엔터티
5) ERD 작성 절차</li>
<li>엔터티를 그린다</li>
<li>엔터티를 적절하게 배치한다</li>
<li>엔터티 간에 관계를 설정한다</li>
<li>관계명을 기술한다</li>
<li>관계의 참여도를 기술한다</li>
<li>관계의 필수 여부를 기술한다</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[CPU 스케줄링]]></title>
            <link>https://velog.io/@ziwon_c/CPU-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81</link>
            <guid>https://velog.io/@ziwon_c/CPU-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81</guid>
            <pubDate>Wed, 19 Apr 2023 06:44:48 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/35d81268-07ba-472b-8598-d0e26296ef58/image.png" alt=""></p>
<h2 id="sjf-스케줄링shortest-job-first-scheduling">SJF 스케줄링(Shortest Job First Scheduling)</h2>
<p>최소 작업 우선 스케줄링이란 각 작업의 프로세서 <strong>실행 시간</strong>을 이용하여 프로세서가 사용 가능할 때 <strong>실행 시간이 가장 짧은 작업에 할당하는 방법</strong></p>
<ul>
<li>최소 작업 우선 스케줄링은 <strong>FIFO 스케줄링</strong>
에서 실행 시간에 따른 할당 방식의 차이가 FIFO와 SJF의 차이점임</li>
<li>장점 : 항상 실행 시간이 짧은 작업을 신속하게 실므로 평균 대기 시간이 가장 짧음</li>
<li>단점 : 아사 현상, 해결 방법으로는 에이징이 있다. 나이 제한을 둠으로써 일정 횟수 이상 밀리면 더 이상 양보하지 않고 작업하는 것, 현대의 프로세스는 사용자와의 상호작용이 빈번하기 때문에 종료 시간을 예측할 수 없다. 따라서 SJF 스케줄링을 사용하기 힘듦, 프로세스가 자신의 작업 시간을 운영체제에 알려주어 해결할 수 있다. 하지만 이를 정확히 알기가 어렵다.</li>
<li>기본적으로 짧은 작업이 항상 실행되도록 설정하므로 불공정한 작업을 실행</li>
<li>반환 시간 = 실행 시간 + 대기 시간</li>
<li>대기 시간 = 반환 시간 - 실행 시간</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ziwon_c/post/f33f0953-134b-4a5a-90a5-f897b73a7653/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/ziwon_c/post/bbc5bc75-66d5-4a0d-979a-d07a626cc9af/image.png" alt=""></p>
<hr>
<h2 id="srt-스케줄링shortest-remaining-time">SRT 스케줄링(Shortest Remaining Time)</h2>
<ul>
<li>• <strong>SJF 방식을 선점 스케줄링 방식으로 변경한 기법임</strong></li>
<li>SJF 스케줄링과 라운드 로빈 스케줄링을 혼합한 방식, 최소 잔류 시간 우선 스케줄링이라고도 함, 준비 큐에 남아 있는 작업시간이 가장 작은 프로세스를 선택, 그리고 타임 슬라이스를 부여하여 작업 시간 제한을 둠.</li>
<li>장점 : SJF 스케줄링과 평균 대기 시간을 비교했을 때 SRT 스케줄링의 평균 대기 시간이 더 짧음</li>
<li>단점 : 현재 실행 중인 프로세스와 큐에 있는 프로세스의 남은 시간을 주기적으로 계산하고, 남은 시간이 더 적은 프로세스와 컨텍스트 스위칭을 해야 함. SJF 스케줄링에는 없던 작업이 추가된 것,운영 체제가 프로세서의 종료 시간을 예측하기 어렵고 아사 현상이 일어나기 때문에 잘 사용하지 않음</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ziwon_c/post/2c37f4b0-69d4-49e2-8249-99cacfd8f745/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/ziwon_c/post/97dd0ec1-55bf-429b-815e-fb7a36afdefa/image.png" alt=""></p>
<hr>
<h2 id="rr-스케줄링round-robin">RR 스케줄링(Round-Robin)</h2>
<p><strong>프로세스가 CPU를 할당받고 작업하는 동안 할당받은 시간(타임 슬라이스)이 지나면 준비 큐의 맨 뒤로 보내는 방식.</strong> 선점형 알고리즘 방식 중 가장 단순하고 대표적인 방식으로 프로세스들이 작업을 완료할 때까지 계속 순환하면서 실행됨. FCFS 스케줄링에서 타임 슬라이스를 추가한 것. 우선 순위는 없음.</p>
<p>타임 슬라이스의 크기를 어떻게 설정하냐에 따라 시스템의 성능이 좌우됨</p>
<ul>
<li><p>타임 슬라이스가 큰 경우
컨텍스트 스위칭 횟수가 적다. 하지만 너무 커질 경우 한 작업이 완료될 때까지 기다려야 하는 것처럼 보임. 만약 크기가 무한대라면 FCFS와 비슷.</p>
</li>
<li><p>타임 슬라이스가 작은 경우</p>
<p>  컨텍스트 스위칭 횟수가 많음. 이로 인해 실제 작업 시간보다 더 많아짐.</p>
</li>
</ul>
<p><strong>따라서 타임 슬라이스는 되도록 작게 설정하되 컨텍스트 스위칭에 걸리는 시간을 고려하여 적당한 크기로 하는 것이 중요함.</strong></p>
<p><img src="https://velog.velcdn.com/images/ziwon_c/post/7918c6fc-3376-408f-88bd-2e4ccee15fde/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/ziwon_c/post/ef7eff89-85c8-4dea-889c-d5910677ce65/image.png" alt=""></p>
<hr>
<h2 id="hrrn-스케줄링highest-response-ratio-next">HRRN 스케줄링(Highest response ratio next)</h2>
<p>HRRN은 Response Ratio를 계산하여 해당 값이 가장 높은 프로세스를 우선적으로 스케줄링하는 기법임.</p>
<ul>
<li>SPN을 변형한 기법 : SRTN보다 현실적임</li>
<li>비선점형 스케줄링</li>
<li>Aging concepts : SPN의 기아 현상을 해결하기 위한 개념임<ul>
<li>나이가 많은(대기 시간이 긴)프로세스를 배려한다는 의미</li>
<li>즉, 프로세스의 대기시간을 고려하여 스케줄링함</li>
</ul>
</li>
<li>Response ratio (응답률) : (대기 시간 + 실행 시간) / 실행 시간<ul>
<li>분자의 대기 시간이 높으면 우선순위가 높아짐</li>
<li>즉, 실행 시간 대비 얼마나 기다렸는지를 고려함</li>
</ul>
</li>
</ul>
<p>SPN의 장점을 취하면서 기아 문제를 방지했지만, 여전히 실행 시간을 예측해야한다(Overhead)는 문제점이 있음</p>
<p><img src="https://velog.velcdn.com/images/ziwon_c/post/f5eb037c-541e-4ed1-91dd-fb9cbcc4103b/image.png" alt=""></p>
<hr>
<h2 id="다단계-피드백-큐mfq-스케줄링multilevel-feedback-queue-scheduling">다단계 피드백 큐(MFQ) 스케줄링(MultiLevel Feedback Queue Scheduling)</h2>
<p> <strong>다 단계 큐 + 동적인 프로세스 우선 순위 변화 적용</strong></p>
<ul>
<li>프로세스 생성 시 가장 높은 우선 순위 준비 큐에 등록되며 등록된 프로세스는 FCFS 순서로 CPU를 할당 받아 실행된다. 해당 큐의 CPU 시간 할당량(Time Quantum)이 끝나면 한 단계 아래의 준비 큐에 들어감</li>
<li>단계가 내려갈수록 시간 할당량(Time Quantum)이 증가함</li>
<li>큐 사이의 프로세스 이동 가능하며 CPU Burst는 낮은 우선순위의 큐, I/O Burst는 높은 우선순위의 큐에 배치함</li>
<li>가장 하위 큐는 FCFS 스케줄링</li>
</ul>
<p>다단계 피드백 큐 스케줄링의 경우 큐의 수, 각 큐에 대한 알고리즘, 우선순위 격상 또는 격하 시기 결정, 처음 프로세스들이 진입해야 할 큐 등등 매우 복잡한 판단을 요구함
<img src="https://velog.velcdn.com/images/ziwon_c/post/34358e1b-2b85-40e9-ab74-9d42094383d7/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로세스와 스레드]]></title>
            <link>https://velog.io/@ziwon_c/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%99%80-%EC%8A%A4%EB%A0%88%EB%93%9C</link>
            <guid>https://velog.io/@ziwon_c/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%99%80-%EC%8A%A4%EB%A0%88%EB%93%9C</guid>
            <pubDate>Sun, 02 Apr 2023 14:24:07 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/fcbefdb9-1678-4ee3-85b5-f4d640bfed90/image.png" alt=""></p>
<h1 id="프로세스의-상태표">프로세스의 상태표</h1>
<p><img src="https://velog.velcdn.com/images/ziwon_c/post/3f8d7416-1544-4931-96d9-4d417963e437/image.png" alt=""></p>
<h2 id="프로세스-상태">프로세스 상태</h2>
<h3 id="생성created">생성(Created)</h3>
<ul>
<li>프로세스 최초 상태로, 주기억장치 적재되지 않고 보조 기억 장치에 저장되어 있는 실행 파일 상태<h3 id="준비ready">준비(Ready)</h3>
</li>
<li>프로세스가 CPU를 사용하여 실행 준비 된 상태</li>
<li>프로세스 상태 리스트 중 준비 리스트에 들어감</li>
<li>프로세스가 우선순위에 의해 정렬됨<h3 id="실행running">실행(Running)</h3>
</li>
<li>프로세스가 CPU를 차지하여 실행 중인 상태</li>
<li>명령어들이 실행되고 있는 상태<h3 id="대기waiting">대기(Waiting)</h3>
</li>
<li>기다림(waiting) 또는 블록(block)상태</li>
<li>I/O 동작의 완료 등 사건 발생을 기다리는 상태</li>
<li>프로세스 상태 리스트 중 블록 리스트에 들어감<h3 id="종료exit">종료(Exit)</h3>
</li>
<li>프로세스 실행이 완료되어 자원을 반납한 상태</li>
</ul>
<h2 id="프로세스-상태-전이">프로세스 상태 전이</h2>
<h3 id="dispatch-준비---실행">Dispatch (준비 -&gt; 실행)</h3>
<ul>
<li>프로세스 생성 상태에서 프로세서만 할당 받으면 실행 상태로 전이 과정</li>
<li>준비 프로세스 중 하나가 CPU 할당 받아 실행 상태로 전이</li>
<li>스케줄링 알고리즘에 의해 수행<h3 id="timeout-실행---준비">Timeout (실행 -&gt; 준비)</h3>
</li>
<li>일정 시간이 지나면 스케줄러에 의해 PCB에 저장, 프로세서 반납 후 준비 상태로 전이<h3 id="block-실행---슬립">Block (실행 -&gt; 슬립)</h3>
</li>
<li>I/O 등의 자원 요청 후 즉시 할당 받을 수 없어, 할당 받을 때까지 기다리고 있는 상태로 전이</li>
<li>I/O 처리는 CPU가 아닌 I/O 프로세스가 담당하기 때문에 발생<h3 id="wake-up-조건만족-슬립---준비">Wake up (조건만족, 슬립 -&gt; 준비)</h3>
</li>
<li>필요한 자원이 할당되면 프로세스는 준비 상태로 전이</li>
<li>장치 관리자로부터 신호 또는 페이지 인터럽트 처리 의해 발생</li>
<li>준비 리스트의 맨 뒤에 붙음</li>
</ul>
<hr>
<h1 id="프로세스-제어-블록-pcb">프로세스 제어 블록 (PCB)</h1>
<p><img src="https://velog.velcdn.com/images/ziwon_c/post/086bc25d-f1eb-4bd5-92a3-45ab48b59deb/image.png" alt=""></p>
<h2 id="프로세스-제어-블록의-구성1">프로세스 제어 블록의 구성(1)</h2>
<h3 id="포인터">포인터</h3>
<ul>
<li>준비 상태나 대기 상태의 큐를 구현할 때 사용</li>
<li>대기 상태에는 같은 입출력을 요구한 프로세스끼리 연결할 때 포인터 사용
<img src="https://velog.velcdn.com/images/ziwon_c/post/1e03fcd5-1787-40df-bf31-7b69dba5f5e9/image.png" alt=""><h3 id="프로세스-상태-1">프로세스 상태</h3>
</li>
<li>프로세스가 현재 어떤 상태에 있는지를 나타내는 정보 (생성, 준비, 실행, 대기..)<h3 id="프로세스-구분자">프로세스 구분자</h3>
</li>
<li>운영체제 내에 있는 여러 프로세스를 구현하기 위한 구분자 -&gt; pid<h3 id="프로그램-카운터">프로그램 카운터</h3>
</li>
<li>다음에 실행될 명령어의 위치를 가리키는 프로그램 카운터의 값<h3 id="프로세스-우선순위">프로세스 우선순위</h3>
</li>
<li>프로세스의 실행 순서를 결정하는 우선순위<h3 id="각종-레지스터-정보">각종 레지스터 정보</h3>
</li>
<li>프로세스가 실행되는 중에 사용하던 레지스터의 값<h2 id="프로세스-제어-블록의-구성2">프로세스 제어 블록의 구성(2)</h2>
<h3 id="메모리-관리-정보">메모리 관리 정보</h3>
</li>
<li>프로세스가 메모리의 어디에 있는지 나타내는 메모리 위치 정보, 메모리 보호를 위해 사용하는 경계 레지스터 값과 한계 레지스터 값 등<h3 id="할당된-자원-정보">할당된 자원 정보</h3>
</li>
<li>프로세스를 실행하기 위해 사용하는 입출력 자원이나 오픈 파일 등에 대한 정보<h3 id="계정-정보">계정 정보</h3>
</li>
<li>계정 번호, CPU 할당 시간, CPU 사용 시간 등<h3 id="부모-프로세스-구분자와-자식-프로세스-구분자">부모 프로세스 구분자와 자식 프로세스 구분자</h3>
</li>
<li>부모 프로세스를 가리키는 PPID와 자식 프로세스를 가리키는 CPID 정보</li>
</ul>
<hr>
<h1 id="문맥교환">문맥교환</h1>
<ul>
<li>CPU를 차지하던 프로세스가 나가고 새로운 프로세스를 받아들이는 작업</li>
<li>실행 상태에서 나가는 프로세스 제어 블록에는 지금까지의 작업 내용을 저장하고, 반대로 실행 상태로 들어오는 프로세스 제어 블록의 내용으로 CPU가 다시 세팅
<img src="https://velog.velcdn.com/images/ziwon_c/post/8c3df6e8-6ec2-4681-8648-c936c40894b6/image.png" alt=""><h2 id="문맥교환-절차">문맥교환 절차</h2>
</li>
<li>인터럽트/시스템 호출 : 운영체제에서 프로세스 스케쥴러에 의해 인터럽트 발생</li>
<li>커널 모드 전환 : 프로세스가 실행되는 사용자모드에서 커널 모드로 전환</li>
<li>현재 프로세스 상태 PCB 저장 : 기존 실행되는 프로세스 정보를 PCB에 저장</li>
<li>다음 실행 프로세스 로드 : PCB에 있는 다음 실행 프로세스 상태 정보 복구</li>
<li>사용자 모드 전환 : 커널 모드에서 사용자 모드로 전환하여 프로세스 실행</li>
</ul>
<hr>
<h1 id="스레드의-정의">스레드의 정의</h1>
<ul>
<li>CPU 스케줄러가 CPU에 전달하는 일 하나</li>
<li>CPU가 처리하는 작업의 단위는 프로세스로부터 전달받은 스레드</li>
<li>운영체제 입장에서의 작업 단위는 프로세스</li>
<li>CPU 입장에서의 작업 단위는 스레드
스레드 : 프로세스의 코드에 정의된 절차에 따라 CPU에 작업 요청을 하는 실행 단위<h2 id="프로세스와-스레드의-차이">프로세스와 스레드의 차이</h2>
</li>
<li>프로세스끼리는 약하게 연결되어 있는 반면, 스레드끼리는 강하게 연결되어 있음<h2 id="멀티태스크와-멀티스레드의-차이">멀티태스크와 멀티스레드의 차이</h2>
</li>
<li>멀티태스크 : 여러 개의 프로세스로 구성된 것</li>
<li>멀티스레드 : 하나의 프로세스에 여러 개의 스레드로 구성된 것, 작업의 부담을 줄이는 프로세스 운영 기법</li>
</ul>
<h2 id="이외">이외</h2>
<ul>
<li>멀티태스킹 : 운영체제가 CPU에 작업을 줄 때 시간을 잘게 나누어 배분하는 기법</li>
<li>멀티프로세싱 : CPU를 여러 개 사용하여 여러 개의 스레드를 동시에 처리하는 작업 환경</li>
</ul>
<h4 id="cpu-멀티스레드">CPU 멀티스레드</h4>
<ul>
<li>한 번에 하나씩 처리해야 하는 스레드를 파이프라인 기법을 이용하여 동시에 여러 스레드를 처리하도록 만든 병렬 처리 기법</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[마이크로 프로세서 과제]]></title>
            <link>https://velog.io/@ziwon_c/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%84%9C-%EA%B3%BC%EC%A0%9C</link>
            <guid>https://velog.io/@ziwon_c/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%84%9C-%EA%B3%BC%EC%A0%9C</guid>
            <pubDate>Sun, 19 Mar 2023 12:24:41 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/bb68f6b9-3890-460a-95d1-18915fa07479/image.png" alt=""></p>
<h2 id="코드">코드</h2>
<pre><code>#include &lt;stdio.h&gt;

typedef struct student {
int num; 
char name[20];
int mic, lin, pro;
int tot;
double avg;
char grade;
} Student;

void input_data(Student *pary); 
void calc_data(Student *pary); 
void print_data(Student *pary); 

int main(void) {
Student ary[5];
input_data(ary);
calc_data(ary);
print_data(ary);
return 0;
}

void input_data(Student *pary) {
for (int i = 0; i &lt; 1; i++) {
printf(&quot;%d 입력하세요 : &quot;, i+1); 
scanf(&quot;%d %s %d %d %d&quot;, &amp;pary[i].num, pary[i].name, &amp;pary[i].mic, &amp;pary[i].lin, &amp;pary[i].pro);
}
}

void calc_data(Student *pary) {
for (int i = 0; i &lt; 1; i++) {
pary[i].tot = pary[i].mic + pary[i].lin + pary[i].pro;
pary[i].avg = (double) pary[i].tot / 3;

if (pary[i].avg &gt;= 90) {
pary[i].grade = &#39;A&#39;;
} 
else if (pary[i].avg &gt;= 80) {
pary[i].grade = &#39;B&#39;;
} 
else if (pary[i].avg &gt;= 70) {
pary[i].grade = &#39;C&#39;;
}
else {
pary[i].grade = &#39;F&#39;;
}
}
}

void print_data(Student *pary) {
for (int i = 0; i &lt; 1; i++) {
printf(&quot;%d,%s,%d,%d,%d,%d,%.lf,%c\n&quot;, pary[i].num, pary[i].name, pary[i].mic, pary[i].lin, pary[i].pro, pary[i].tot, pary[i].avg, pary[i].grade);
}
}</code></pre><h2 id="실행결과">실행결과</h2>
<p><img src="https://velog.velcdn.com/images/ziwon_c/post/d6b34ddf-718e-45a4-a9e5-cbcecc105a18/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹 프로그래밍]]></title>
            <link>https://velog.io/@ziwon_c/%EC%9B%B9-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</link>
            <guid>https://velog.io/@ziwon_c/%EC%9B%B9-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</guid>
            <pubDate>Thu, 09 Mar 2023 11:20:57 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/e10b488b-7297-4209-91bb-047ef417db27/image.png" alt=""></p>
<h1 id="example1">example1</h1>
<pre><code>&lt;script&gt;

function myfunction1(){

document.getEelmentById(’result’).value = “버튼 1 눌러짐”;

}

function myfunction2(){

document.getEelmentById(’result’).value = “버튼 2 눌러짐”;

}

&lt;/script&gt;

&lt;input id = result type=text&gt;

&lt;input type = button value=”버튼1 눌러주세요” onclick=myfunction1()&gt; // 쌍따옴표가 있다면 출력되고 없다면 출력 안됨.

&lt;input type = button value=버튼2 onclick=myfunction2()&gt;</code></pre><h1 id="example2">example2</h1>
<pre><code>// response, request 사이에 php가 끼여있다라고 생각!

// 

여기는 html로 해석됩니다&lt;BR&gt;

&lt;?php

echo “여기는 php의 공간입니다.”; // 출력문

echo “&lt;input type=text&gt;”; // 가능함(html문 첨가)

---

int num = 10; // 아두이노 버전

$num = 10; // php 버전(변수에 $ 기호 붙여야 함)

$num = “10”; // 문자열

// php는 “10” * 10 = 100으로 나옴

---

int num[] = {1,2,3,4}; // c언어의 배열

int num[4];

int num[0] = 1;

int num[1] = 2;

int num[2] = 3;

int num[3] = 4;

$num = {1,2,3,4}; // php의 배열

echo $num[2]; // 3이 출력됨

---

for($i=0;$i&lt;4;$i++){ // php 반복문

echo $num[$i] . “&lt;BR&gt;”;

// 위와 밑은 같은 결과 출력하는 코드

echo $num[$i];

echo “&lt;BR&gt;”;

}

---

$num = [1,2,3,4,5,6];

ehco count($num); // 배열의 갯수를 출력

$cnt = count($num);

?&gt;</code></pre><h1 id="example3">example3</h1>
<p><a href="http://localhost">localhost</a> = 127.0.0.1 (내 것을 쓰겠다!!)</p>
<p><a href="http://localhost">localhost</a>는 서버의 메인 페이지(index.php)</p>
<p>(IP 주소 = 루트 경로) / (test.php = Request)</p>
<p>404 error : 서버가 찾아보고 유효하지 않을 경우</p>
<p>웹 서버 (정보를 가진 쪽)</p>
<p>웹 클라이언트 (정보를 요구)</p>
<p>1) 클라 → 서버 (접속 시도)</p>
<p>2) 클라 → 서버 (요구 사항 제출)</p>
<p>3) 서버 → 클라 (응답)</p>
<p>4) 연결 해제</p>
<p>url(주소 + 데이터 + 규칙)</p>
<ul>
<li><a href="http://localhost">localhost</a> : 서버와 클라이언트가 같은 곳에 있을 때</li>
<li>ip주소 : 서버의 메인 페이지(index)</li>
<li>plain text : 크롬 브라우저에 의해서 해</li>
</ul>
<p>php의 단점</p>
<ul>
<li>서버 → 클라 (접속하지 않으면 평생 접속 X)</li>
</ul>
<p>⭐ node-red (node.js 블록 코딩)</p>
<p><a href= O></a></p>
<p>절대 주소 : IP 주소</p>
<p>ex) <a href = 10.129.55.189/test.php>절대 주소</a></p>
<p>상대 주소 : 웹 페이지 간 옮겨갈 때</p>
<p>ex) <a href = test.php>상대 주소</a></p>
<p><a href = /test.php>상대 주소</a></p>
<p><a href = ../test.php>상대 주소</a></p>
<pre><code>&lt;?php

// name = 지원

if(isset($_GET[’name’])){

echo $_GET[’name’];

echo “&lt;BR&gt;”;

else{

echo “name이 존재하지 않습니다”;

}

if(isset($_GET[’age’])){

echo $_GET[’age’];

echo “&lt;BR&gt;”;

}

else{

echo “age이 존재하지 않습니다”;

}

echo $_GET[’name’];

echo “&lt;BR&gt;”;

echo $_GET[’age’];

echo “&lt;BR&gt;”;

?&gt;</code></pre><h1 id="example4">example4</h1>
<pre><code>&lt;?php

$data = = ‘&lt;input type=\”text=\”&gt;”; // 쌍따옴표 안에 또 쌍따옴표가 있다면 역 슬래시( \ )를 써야 한다. (나중에 이런 경우 많음)

echo $data;

?&gt;</code></pre><h1 id="example5">example5</h1>
<pre><code>&lt;table border=1 width = 300&gt;

&lt;tr&gt;

&lt;th&gt;a&lt;/th&gt;

&lt;th&gt;b&lt;/th&gt;

&lt;th&gt;c&lt;/th&gt;

&lt;th&gt;d&lt;/th&gt;

&lt;/tr&gt;

&lt;?php

$myarray = [

[’녹칸다1’, ‘21’, ‘남성’, ‘aa1’],

[’녹칸다2’, ‘22’, ‘남성’, ‘aa2’],

[’녹칸다3’, ‘23’, ‘남성’, ‘aa3’],

[’녹칸다4’, ‘24’, ‘남성’, ‘aa4’]

];

for($i=0;$i&lt;count($myarray);$i++){

echo “&lt;tr&gt;”;

for($j=0;$j&lt;4;$j++){

echo “&lt;td&gt;” . $myarray[$i][$j].”&lt;/td&gt;”;`

}

echo “&lt;/tr&gt;”;

}

&lt;/table&gt;

?&gt;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux]웹 서버(아파치)]]></title>
            <link>https://velog.io/@ziwon_c/Linux%EC%9B%B9-%EC%84%9C%EB%B2%84%EC%95%84%ED%8C%8C%EC%B9%98</link>
            <guid>https://velog.io/@ziwon_c/Linux%EC%9B%B9-%EC%84%9C%EB%B2%84%EC%95%84%ED%8C%8C%EC%B9%98</guid>
            <pubDate>Tue, 21 Feb 2023 12:58:15 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/2030f480-d873-484b-8e4b-8affab26cf32/image.png" alt=""></p>
<h2 id="설치">설치</h2>
<p>아파치를 설치할 때는 sudo apt-get update;를 하고 sudo apt-get apache2를 하면 설치가 완료된다. sudo service apache2 start를 하면 아파치가 켜진다. stop은 멈춤, restart는 멈췄다가 다시 키는 것이다. 잘 설치되었는지 보는 법은 sudo apt-get install elinks를 하면 설치되는 프로그램이 있다. 그 다음 elinks를 치면 url를 검색하라고 되어있고, 검색을 하면 검색 결과가 나와 웹 브라우징을 할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux]인터넷, 네트워크 그리고 서버]]></title>
            <link>https://velog.io/@ziwon_c/Linux%EC%9D%B8%ED%84%B0%EB%84%B7-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%84%9C%EB%B2%84</link>
            <guid>https://velog.io/@ziwon_c/Linux%EC%9D%B8%ED%84%B0%EB%84%B7-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%84%9C%EB%B2%84</guid>
            <pubDate>Tue, 21 Feb 2023 12:56:36 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/91a0e5dc-4a96-4f19-aac5-519951ddba37/image.png" alt=""></p>
<h2 id="인터넷-1">인터넷 1</h2>
<p>웹 브라우저는 주소창이 있고, 주소를 치면 웹과 연결이 된다. 구글을 치게 되면 구글 닷컴에 접속이 들어가 구글에서 정보를 다시 우리에게 보낸다.  우리가 request하고 구글이 respose하는 과정이다.이 때 우리는 client이고 구글이 server가 되는 것이다. 서버에 접속하는 방법은 ip address라는 것이 있다. ping google.com이라고 하면 ip가 나온다. 그 ip를 복붙하여 검색하면 구글창이 나오게 된다. DNS Server는 많은 ip를 알고있는 전화번호부같은 것이다.</p>
<h2 id="인터넷-2">인터넷 2</h2>
<p>ip addr라고 명령을 친 다음 inet이라고 적혀 있는 부분이 ip address이다. curl <a href="http://google.com">google.com</a>이라고 친다면 구글 창의 html 코드를 가져와서 보여준다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux]그룹]]></title>
            <link>https://velog.io/@ziwon_c/Linux%EA%B7%B8%EB%A3%B9</link>
            <guid>https://velog.io/@ziwon_c/Linux%EA%B7%B8%EB%A3%B9</guid>
            <pubDate>Tue, 21 Feb 2023 12:54:53 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/b695410d-7926-4a98-abfd-3e9689307537/image.png" alt=""></p>
<h2 id="그룹의-개념">그룹의 개념</h2>
<p>user, other이 아닌 group에 대해 권한을 주면 싶다면 그 group에게 이름을 주고 이 파일에 그 group을 부여한다. 그리고 그 파일에 대한 그룹 권한을 r, w, x를 주는 것을 통해 그룹에 속하는 사람들이 읽기, 쓰기, 수정을 할 수 있도록 해준다.</p>
<h2 id="groupadd-명령어">groupadd 명령어</h2>
<p>groupadd developer라고 하면 Permission denied가 뜬다. 즉, 일반 사용자가 사용할 수 없다는 것이다. sudo !! 라고 하면 직전에 쓴 명령어를 가져오기 때문에 group이 만들어질 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux]사용자 권한]]></title>
            <link>https://velog.io/@ziwon_c/Linux%EC%82%AC%EC%9A%A9%EC%9E%90-%EA%B6%8C%ED%95%9C</link>
            <guid>https://velog.io/@ziwon_c/Linux%EC%82%AC%EC%9A%A9%EC%9E%90-%EA%B6%8C%ED%95%9C</guid>
            <pubDate>Mon, 20 Feb 2023 15:10:49 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/262f95d0-d7d8-489d-8756-235ab3a7dd85/image.png" alt=""></p>
<h2 id="권한permission">권한(Permission)</h2>
<p>유닉스 계열의 시스템에서는 파일과 디렉터리를 권한을 지정할 수 있다. 파일과 디렉터리에 관해 읽기, 쓰기, 실행의 권한을 지정하는 것을 Permission이라고 한다. touch perm.txt라는 파일을 만든다. ls -l perm.txt이라고 하면 파일에 대한 상세 보기를 보여준다. 이때 이 파일이 누구의 것인지 알 수 있다.같은 컴퓨터 내에서 다른 사람이 echo ‘hello’ &gt; perm.txt이러한 명령을 치게 된다면 원래는 수정이 되지만 다른 사람이 실행을 하면 수정이 되지 않는다. ls -l perm.txt의 내용을 살펴보자.</p>
<p>-rw-rw-r— 1 egoing egoing 0 Dec 4 23:19 perm.txt</p>
<p>우선 첫 번째 (-)는 기본적인 파일을 뜻한다.</p>
<p>디렉터리인 경우는 D라는 알파벳으로 되어있다.두 번째(rw-rw-r—)은 액세스 모드라는 것이다. r: read, w: write, - 혹은 x : excute라는 뜻이다. 세 번째는 owner(egoing), 네 번째는 group(egoing)을 뜻한다.</p>
<h2 id="권한-변경chmod">권한 변경(chmod)</h2>
<p>파일의 소유자에서 액세스 모드를 없애기 위해서는 chmod o-r perm.txt라고 친다면 읽기 기능이 사라진다. 다른 사용자가 cat perm.txt를 친다면 Permission denied가 뜨게 된다. 권한을 추가할 때는 chmod o+r perm.txt라고 입력하면 된다. chmod u-r perm.txt라고 한다면 user의 권한을 막아버린다는 뜻이다. </p>
<h2 id="실행의-개념과-권한-설정">실행의 개념과 권한 설정</h2>
<p>어떤 파일에 대해 실행 가능한 파일로 할 것이냐라고 권한 지정하는 게 실행 권한이다. <a href="http://hi-machine.sh">hi-machine.sh</a>라는 파일을 실행 시키고 싶다면 /bin/bash hi-machine.sh라는 명령어를 입력하면 된다. ./hi-machine.sh라고 하면 실행이 안되는데 이 친구에게 권한을 주기 위해서는 chmod u+x hi-machine.sh;라고 입력하면 된다. 그러면 파일의 내용이 잘 출력이 된다. </p>
<h2 id="directory의-권한">directory의 권한</h2>
<p>chmod o-r perm이라는 명령어를 치면 읽기 권한이 사라진다. chmod o+w perm을 하게 되면 touch test라는 파일을 다른 사용자가 만들어도 생성이 가능하다. 디렉터리 모두를 모드 바꾸고 싶을 때는 chmod -R o+w perm이라고 입력하면 된다.</p>
<h2 id="chmod-사용법-정리">chmod 사용법 정리</h2>
<p>파일의 권한을 바꿀 때는 chmod 222 perm.txt라고 한다면 모든 사용자가 www가 된다. chmod 444 perm.txt를 하면 모든 사용자가 rrr가 된다. 쓰기와 실행을 같이 하고 싶다면 333를 입력하면 된다. 외울 필요는 없고 인터넷 검색을 하면 된다. chmod a+r perm.txt는 모든 종류의 사용자에 대해 r을 더한다는 뜻이다. chmod a+w perm.txt는 w 값을 가지게 된다는 의미이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[사용자 관리]]></title>
            <link>https://velog.io/@ziwon_c/%EC%82%AC%EC%9A%A9%EC%9E%90-%EA%B4%80%EB%A6%AC</link>
            <guid>https://velog.io/@ziwon_c/%EC%82%AC%EC%9A%A9%EC%9E%90-%EA%B4%80%EB%A6%AC</guid>
            <pubDate>Sun, 19 Feb 2023 13:59:17 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/1745b4c6-0544-429f-969d-d5da1c9474c3/image.png" alt=""></p>
<h2 id="다중-사용자-소개">다중 사용자 소개</h2>
<p>다중 사용자 시스템을 사용하는 순간에 시스템의 복잡도는 어려워지게 되어있다. </p>
<h2 id="id와-who">id와 who</h2>
<p>id라는 명령어는 내가 누군지 식별한다는 뜻이다. 유저의 아이디, 어떤 그룹에 속해있는지에 대해 알려준다. who라는 명령어는 이 시스템에 지금 누가 접속했는지 보여준다. </p>
<h2 id="root-user">Root User</h2>
<p>super user는 유저의 이름이 root라는 이름으로 되어 있고, 달러 표시가 되어 있는 것은 일반 유저라는 뜻이다. super user는 #으로 되어있다. 슈퍼 유저가 되기 위해서는 su라는 명령어를 쓰면 된다. su - root라고 명령을 치면 된다. 다시 일반 유저가 되고 싶다면 exit를 치면 된다. sudo passwd -u root라고 하면 rock이 풀린다. sudo passwd -l root라고 하면 rock이 다시 잠겨진다.</p>
<h2 id="add-user">Add User</h2>
<p>sudo useradd -m duru를 치고 password를 치면 duru라고 하는 사용자의 디렉토리가 생긴다. su -duru를 치면 패스워드가 생기는데 아직 없기 때문에 sudo passwd duru한 다음 duru의 패스워드를 입력하여 로그인을 하면 된다. sudo usermod -a -G sudo duru라고 한 뒤 아무 말이 없다면 우분투 리눅스에서 터미널로 사용자 계정 만들고 관리자 계정(sudo)을 등록하는 게 잘 되었다는 의미이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux]프로세스의 실행]]></title>
            <link>https://velog.io/@ziwon_c/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%9D%98-%EC%8B%A4%ED%96%89</link>
            <guid>https://velog.io/@ziwon_c/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%9D%98-%EC%8B%A4%ED%96%89</guid>
            <pubDate>Sun, 19 Feb 2023 10:41:41 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/ac1bf4a4-f5ed-4c63-b030-dfd7dd040d18/image.png" alt=""></p>
<h2 id="백그라운드-실행">백그라운드 실행</h2>
<p>앞의 프로그램을 쓰다가 뒤에 있는 프로그램, 즉 background(백그라운드)에서 실행되던 프로그램은 앞으로 오면서 foreground(포그라운드) 프로그램이 되고, 앞에 있던 건 background(백그라운드)가 된다. nano라는 명령어를 치고, 에디터를 편집한 후 hello.html로 저장한다. 이 hello.html라는 파일을 끄지 않은 상태에서 다른 작업을 하고 싶다면 control + z를 누르면 할 수 있다. 이 상태에서 fg(foreground)라는 명령어를 입력하게 되면 hello.html이 다시 켜지게 된다. jobs라는 명령어를 치면 나노라는 프로그램이 백그라운드로 실행되고 있다는 창이 뜬다. 여기서 vim이라는 나노와의 라이벌인 에디터를 실행시켜보자. 여기서 control + z를 누르면 다른 명령어를 실행시킬 수 있는 상태가 된다. 그럼 vim은 백그라운드로 간다. 만약 vim의 숫자가 2인 상태일 때 vim을 실행 시키고 싶다면 fg %2라는 명령을 입력하면 된다.  만약 vim을 죽이고 싶다면 kill %2라는 명령을 입력하면 된다. 그래도 안된다면 kill -9 %2를 치면 완벽하게 종료를 할 수 있다. 프로그램이 실행할 때부터 백그라운드로 보내고 싶을 때는 ls -R라는 옵션을 검색하면 되는데 자신이 지정한 디렉토리 밑에 있는 모든 디렉토리를 뒤져서 파일과 디렉토리를 보여준다. ls -R / &gt; result.txt 2&gt; error.log라는 명령은 실행된 결과를 result.txt라는 파일에 저장하고 에러가 있다면 error.log에 저장이 된다. ls -alR / &gt; result.txt 2&gt; error.log &amp;라는 명령은 즉각, 실행이 백그라운드로 가면서 그 다음 명령을 입력할 수 있는 상태가 된다.</p>
<h2 id="데몬의-개념">데몬의 개념</h2>
<p>daemon의 특성은 항상 실행되고 있다는 점이다. 하지만 ls, rm, mkdir이라는 실행 프로그램은 끌 수 있지만 daemon은 항상 실행한다는 차이점이 있다. </p>
<h2 id="service와-자동실행">service와 자동실행</h2>
<p>웹 서버의 대표적인 것으로 아파치라는 웹 서버가 있다. sudo apt-get install apache2라고 하면 아파치라는 웹 서버를 설치하게 된다. 아파치는 cd /etc/init.d/라는 명령을 치면 아파치의 위치를 볼 수 있다.  이 명령은 데몬 프로그램의 디렉토리를 보여준다. sudo service apache2 start라고 명령어를 치면 아파치가 켜진다. 끄고 싶다면 sudo service apache2 stop이란 명령을 치면 된다. 이런 데몬들은 자동으로 켜져야 하기 때문에 cd ..라는 명령을 치고, cd r이라고 치면 rc3.d라는 디렉토리와 rc5.d라는 디렉토리가 있는데 rc3.d 디렉토리는 우리가 지금 운영체제를 콘솔로 구동하고 있는 경우이고, GUI방식으로 구동 중이면 rc5.d 디렉토리이다. 바로 가기의 이름 앞에 S라고 시작된다면 이 프로그램은 rc3.d 디렉토리에 있어서 콘솔로 부동된다는 뜻이다. k로 시작하는 이름은 프로그램은 자동으로 실행되지 않는다는 뜻이다. </p>
<h2 id="정기적으로-실행cron">정기적으로 실행(cron)</h2>
<p>cron은 정기적으로 명령을 실행시켜주는 소프트웨어이다. 데이터를 정기적으로 백업하거나 전송하는 경우에 사용한다. crontab -e라고 명령을 치면 하고자 하는 일을 정의할 수 있다.에디터는 편한 에디터의 숫자를 선택하면 된다. 정기적으로 하고 싶은 작업을 적어주면 크론에서 실행시켜준다. date라는 명령은 현재 시간을 알려주는 명령이다. tail date.log 라는 명령은 date.log라는 파일의 제일 뒤쪽의 텍스트를 출력해준다. tail -f date.log는 데이터 점 로그라는 파일에 뒤쪽에 텍스트가 추가되면 자동으로 리프레시(refresh)해준다. 크론은 시스템 관리에서 매우 중요한 역할을 한다.</p>
<h2 id="쉘을-시작할-때-실행">쉘을 시작할 때 실행</h2>
<p>alias l=’ls -al’라고 해주면 l이라고 입력하면 ls -al의 내용이 나온다.  alias가 ls -al에 별명을 붙여준 것이다. alias ..=’cd..’은 cd..에 ..이라는 별명을 붙여준 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux]파일을 찾는 법]]></title>
            <link>https://velog.io/@ziwon_c/%ED%8C%8C%EC%9D%BC%EC%9D%84-%EC%B0%BE%EB%8A%94-%EB%B2%95</link>
            <guid>https://velog.io/@ziwon_c/%ED%8C%8C%EC%9D%BC%EC%9D%84-%EC%B0%BE%EB%8A%94-%EB%B2%95</guid>
            <pubDate>Sat, 18 Feb 2023 15:46:58 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/83b2cacb-6ff4-4e7e-b063-6c318c1855d0/image.png" alt=""></p>
<h2 id="locate와-find">locate와 find</h2>
<p>파일을 찾는 방법을 알아볼 것이다. locate [파일의 이름]이라는 명령어를 치면 내가 찾는 이름의 파일을 띄워준다. locate의 중요한 특징은 검색 작업을 수행할 때 데이터 베이스를 뒤진다. 데이터가 저장되어 있는 데이터 베이스는 파일들의 데이터가 저장되어 있기 때문에 훨씬 더 빠르게 파일을 가져올 수 있다. 이렇게 locate가 사용하는 데이터 베이스를 mlocate라고 한다. sudo updatedb라는 명령어를 치면 여러가지 정보들을  저장한다.  </p>
<p>find라는 명령어는 디렉토리를 뒤지기 때문에 locate보다는 느리지만 다양한 사용법들을 사용한다. find / 라는 명령어는 root 디렉토리부터 찾겠다는 뜻이고, find . 이라는 명령어는 현재 디렉토리부터 하위 디렉토리로 찾겠다는 뜻이다. find / -name .log 라는 명령어는 -name이 파일의 이름으로 찾겠다는 뜻이고, .log라고 치면 컴퓨터에 있는 모든 log파일을 찾아준다. 그리고 Permission denied라고 나오는 것은 현재 자신의 권한으로는 접근할 수 없는 디렉토리를 뒤지려고 하기 때문에 뜬다. 그럴 때엔 sudo find / -name .log라는 명령어를 쓰면 된다. 홈 디렉토리 같은 경우는 자신의 디렉토리이기 때문에 sudo를 쓸 필요가 없다. </p>
<p>find . -type f -name “tecmint.txt” -exec rm -f {} ; 라는 명령어는 자신이 머물고 있는 디렉토리에서 파일을 찾는데(find) 형태는 파일이고(-type f) 이름은 tecmint.txt이여야 하고(-name “tecmint.txt”)  파일을 삭제하는 것을 실행시켜야 한다는(-exec rm -f {}) 뜻이다.</p>
<h2 id="whereis와-path">whereis와 $PATH</h2>
<p>whereis라는 명령은 자신이 원하는 실행 파일을 찾아주는 명령이다. whereis ls라고 치면 여러 경로를 찾아주는데 /bin/ls라고 되어 있는 것은 자신이 찾는 ls라는 파일이 bin 밑에 있다는 뜻이다. man whereis라는 명령어를 입력하면 사용 설명서를 볼 수 있다. 이 사용 설명서에서 관심가져야할 부분은 실행 파일, 소스, 메뉴얼을 찾아준다는 내용과 $PATH, $MANPATH에서 내용을 뒤진다는 점인데 $PATH를 중요하게 생각해야 한다. $PATH라는 것은 변수이고, 변수에는 데이터가 들어가 있다. 그 데이터를 화면에 출력하고 싶으면 echo $PATH라고 입력하면 $PATH 라는 변수에 담겨있는 데이터들이 echo를 통해서 화면에 출력이 된다. $PATH라는 변수는 자신이 만들지 않아도 기본적으로 가지고 있다. ls를 입력하면 운영체제에서는 $PATH라는 변수에 저장되어 있는 데이터 중에서 ls라는 실행 파일이 존재하는지를 파악한다. ls라는 명령어가 발견되면 실행시킨다. $PATH처럼 자신이 만들지 않은 기본적으로 가지고 있는 변수를 ‘환경변수’라고 부른다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux]프로세스의 개념]]></title>
            <link>https://velog.io/@ziwon_c/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%9D%98-%EA%B0%9C%EB%85%90</link>
            <guid>https://velog.io/@ziwon_c/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%9D%98-%EA%B0%9C%EB%85%90</guid>
            <pubDate>Sat, 18 Feb 2023 14:56:50 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/7ab96df3-84fb-418f-b564-8e881c66e75a/image.png" alt=""></p>
<h2 id="컴퓨터의-구조">컴퓨터의 구조</h2>
<p>스토리지와 메모리의 공통점은 정보를 저장한다는 공통점이 있다. 하지만 스토리지는 가격이 싸고, 메모리는 가격이 비싸다. 그리고 스토리지는 용량이 크고, 속도가 엄청나게 느리다. 메모리는 용량이 작고, 속도가 빠르다. </p>
<p>cpu가 동작할 땐 굉장히 빠르게 동작한다. 스토리지가 cpu의 속도를 따라올 순 없다. 프로그램은 스토리지에 깔려있다. 그 프로그램을 읽어서 메모리에 적재 시킨 후 그 프로그램을 cpu가 읽어 동작을 한다. 사용자가 입력하는 명령어는 bin, sbin이라는 디렉토리에 저장되어 있다. 프로세스란 실행되고 있는 상태의 프로그램을 뜻한다. 그 프로세스를 처리하는 곳이 프로세서이다.</p>
<h2 id="프로세스-모니터링">프로세스 모니터링</h2>
<p>ps라는 명령어는 프로세스 리스트를 보여주는 명령이다. ps aux | grep apache 라는 명령어를 입력하면 아파치라는 텍스트를 포함하는 프로세스만을 화면에 출력해준다. PID란 프로세스의 아이디이다. 그리고 프로세스의 식별자를 안다면 말썽 부리는 프로그램을 죽일 수 있다. 죽이는 방법은 sudo kill [프로세스 아이디] 라고 명령어를 치면 프로그램을 정지 시킬 수 있다. sudo top이라고 명령어를 치면 프로세스의 리스트를 볼 수 있다. 하지만 이 프로그램보다 선호하는 것이 htop이다. 설치는 sudo apt-get install htop이라는 명령어를 치면 된다. sudo htop을 치면 된다. 그 다음 cpu를 치면 cpu를 기준으로 정렬이 된다. 여기 있는 프로세스가 물리적으로 얼마나 메모리를 쓰고있는가에 대한 퍼센트는 mem를 보면 되고, 그 실제적인 메모리 용량은 res 라고 되어 있는 부분을 보면 된다. Load average라는 부분은 cpu의 점유율과 관련된 부분이다. 1번째 자리는 1분간의 cpu 점유율을 뜻한다. htop에서 빠져나가려면 F10을 누르면 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux]쉘과 커널]]></title>
            <link>https://velog.io/@ziwon_c/Linux%EC%89%98%EA%B3%BC-%EC%BB%A4%EB%84%90</link>
            <guid>https://velog.io/@ziwon_c/Linux%EC%89%98%EA%B3%BC-%EC%BB%A4%EB%84%90</guid>
            <pubDate>Sat, 18 Feb 2023 11:05:26 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/8aa8c53a-03d3-47e0-8b1b-960497a1b137/image.png" alt=""></p>
<h2 id="bash-vs-zsh">bash vs zsh</h2>
<p>리눅스에서 echo “hello”라는 명령어를 입력하면 hello라는 문자를 출력해준다. ehco$0이라는 명령어를 치고 -bash가 나온다면 쉘 중에서 bash라는 프로그램을 쓴다는 이야기이다.다음으로 zsh이 나온다면 zshell이라는 shell이 동작하는 상태이다. bash와 zsh는 부모 같은 관계이다. 하지만 zsh에는 bash에는 없는 추가적인 기능이 있다.</p>
<h2 id="shell-script">Shell Script</h2>
<p>ls /bin이라는 명령어를 치면 기본 프로그램들의 디렉토리를 볼 수 있다. 많은 명령들이 파일의 형태로 존재하는 프로그램이었다는 것을 알 수 있다. if [ -d bak ];라는 명령어의 의미는 현재 디렉터리에 bak라는 디렉터리가 존재하는가 라는 뜻이다. if ! [ -d bak ]; then라는 명령어는 bak라는 디렉터리가 존재하지 않을 때를 의미한다.  셸 스크립트란 어떤 셸 명령어들이 실행 되어야 하는 순서, 방법을 각본을 짜서 저장 해 놓은 파일을 뜻한다. </p>
<h2 id="directory-structure">Directory structure</h2>
<p>디렉토리는 어떤 데이터 또는 실행할 수 있는 프로그램을 정리 정돈 하는 수단이다. ‘/’는 최상의 디렉토리를 뜻한다. 이 디렉토리를 우리는 root라고 한다. bin이라는 디렉토리는 바이너리를 줄인 말이고 바이너리는 이진수라는 뜻이다. 실행가능한 프로그램을 바이너리라고도 부른다. 그러므로 사용자들이 사용하는 프로그램의 디렉토리들이 있다.  sbin은 바이러리 실행 프로그램이고, 시스템 프로그램이다. </p>
<p>그리고 시스템 관리자의 역할도 하는데 쉽게 얘기해 root user나 이 시스템을 관리하는 목적을 가진 사용자들이 사용하는 프로그램들이 있다. 즉, 일반 사용자들이 쓰지 않고, 관리자 root 사용자가 쓰는 프로그램들은 sbin에 있다는 뜻이다. 
etc라는 디렉토리는 설정을 의미하는데 프로그램이 동작하는 방법을 우리가 바꾸고 싶을 때 우리는 설정을 사용한다.  컴퓨터가 동작하는 설정에 대한 변경을 할 수 있다. 
var이라는 디렉토리는 내용이 바뀔 수 있고, 용량이 바뀔 수 있다는 뜻이다. var 디렉토리 안에 있는 파일들은 내용이 바뀔 수 있다는 특성이 있다. tmp라는 디렉토리는 임시파일들을 저장하는 곳이다. 여기엔 영구적으로 저장할 파일을 넣으면 안된다. 
home이라는 디렉토리는 사용자들의 디렉토리이다. 
lib라는 곳은 여러 프로그램들이 공통적으로 사용하는 라이브러리이다. 
usr이라는 디렉토리의 밑에는 bin이라는 디렉토리가 있다. 우리가 설치하는 프로그램들이 적당한 위치의 usr에 설치되게 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux] 리눅스 명령어 기초]]></title>
            <link>https://velog.io/@ziwon_c/Linux-%EB%A6%AC%EB%88%85%EC%8A%A4-%EB%AA%85%EB%A0%B9%EC%96%B4-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@ziwon_c/Linux-%EB%A6%AC%EB%88%85%EC%8A%A4-%EB%AA%85%EB%A0%B9%EC%96%B4-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Thu, 16 Feb 2023 14:04:53 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/aca8606f-a94a-47cf-974a-a1eeb9348b0c/image.png" alt=""></p>
<h1 id="--help">--help</h1>
<p>사용 설명서를 보여주는 명령어이다.</p>
<h1 id="man">man</h1>
<p>man 또한 사용 설명서를 보여주는 명령어이지만 --help와는 다른 점이 전용 페이지로 이동하여 더욱 상세한 내용을 보여준다는 차이점이 있다.</p>
<h1 id="mkdir">mkdir</h1>
<p>mkdir --help는 사용법을 알려주고, mkdir --version은 버전을 알 수 있는 명령어이다.</p>
<h1 id="sudo">sudo</h1>
<p>sudo란 super user do의 줄임말이다. 다른 사용자의 보안 권한, 보통 슈퍼유저로서 프로그램을 구동할 수 있도록 하는 명령어이다.</p>
<h1 id="nano">nano</h1>
<p>파일을 편집하는 명령어이다. nano라고 Enter를 치면 파일을 편집할 수 있는 편집기 화면이 뜬다. 파일을 저장하고 싶다면 Ctrl+o를 누르면 원하는 파일의 이름을 적으면 된다. Ctrl+x를 누르면 탈출할 수 있다. 다시 그 파일을 수정하고 싶다면 nano [파일명]이라는 명령어를 입력하면 된다. </p>
<h1 id="apt">apt</h1>
<p>리눅스에서의 대표적인 패키지 매니저이다. sudo apt-get update; 라는 명령어를 치면 인터넷을 통해 최신 상태의 소프트웨어 목록을 다운 받아 놓는다. </p>
<h1 id="wget">wget</h1>
<p>wget [다운로드 url]이라는 명령어를 입력하게 되면 다운로드라는 이름으로 다운로드가 되게 된다. 이 파일의 이름을 바꾸기 위해서는 wget -O [바꿀 명] [다운로드 url]이라는 명령어를 입력하면 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux] 디렉토리와 파일 관련 명령어]]></title>
            <link>https://velog.io/@ziwon_c/Linux-%EB%94%94%EB%A0%89%ED%86%A0%EB%A6%AC%EC%99%80-%ED%8C%8C%EC%9D%BC-%EA%B4%80%EB%A0%A8-%EB%AA%85%EB%A0%B9%EC%96%B4</link>
            <guid>https://velog.io/@ziwon_c/Linux-%EB%94%94%EB%A0%89%ED%86%A0%EB%A6%AC%EC%99%80-%ED%8C%8C%EC%9D%BC-%EA%B4%80%EB%A0%A8-%EB%AA%85%EB%A0%B9%EC%96%B4</guid>
            <pubDate>Tue, 07 Feb 2023 16:05:25 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/fa36e8fa-c210-4a39-b6a2-b3ea4af19a52/image.png" alt=""></p>
<h1 id="ls">ls</h1>
<p>ls는 현재 디렉토리의 파일 목록을 출력하는 명령어이다. ls -l은 현재 위치하고 있는 파일과 디렉토리를 더 자세히 보여주는 명령어이다. 이렇게 ls 뒤에 -l 이나 -a를 붙이는 것을 파라미터라고 부른다. 또는 옵션이라고도 한다.</p>
<h1 id="pwb">pwb</h1>
<p>pwb는 현재 위치하고 있는 디렉토리를 알려주는 명령어이다.</p>
<h1 id="mkdir">mkdir</h1>
<p>디렉토리를 만드는 명령어이다. &#39;mkdir 만들고 싶은 디렉토리명&#39;이라는 명령어를 입력하면 된다.</p>
<h1 id="touch">touch</h1>
<p>&#39;touch 파일명&#39;이라는 명령어는 비어있는 파일을 만들어주는 명령어이다.</p>
<h1 id="cd">cd</h1>
<p>cd는 디렉토리를 바꾼다는 명령어이다. 파일명을 입력할 때 tap키를 누르면 자동완성이 된다. cd..은 현재 디렉토리의 부모 디렉토리로 이동하는 명령이다. 그리고 현재 디렉토리는 &#39;.&#39;이다. 또한 &#39;cd/&#39;는 최상위 디렉토리로 이동한다는 뜻이다.</p>
<h1 id="rm">rm</h1>
<p>rm은 remove를 줄인 명령어이다. 그러므로 삭제를 역할한다. 하지만 디렉토리를 삭제할 땐 &#39;rm -r 디렉토리명&#39;이라는 명령어로 삭제해야 한다. rm --help는 명령어의 사용 방법을 준다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Node.js] query객체의 사용법]]></title>
            <link>https://velog.io/@ziwon_c/Node.js-query%EA%B0%9D%EC%B2%B4%EC%9D%98-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@ziwon_c/Node.js-query%EA%B0%9D%EC%B2%B4%EC%9D%98-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Tue, 31 Jan 2023 14:50:48 GMT</pubDate>
            <description><![CDATA[<h1 id="⭐쿼리스트링이란">⭐쿼리스트링이란?</h1>
<p>사용자가 입력 데이터를 전달하는 방법 중의 하나로, url 주소에 미리 협의된 데이터를 파라미터를 통해 넘기는 것을 말한다.
쉽게 말해 예를 들어 <a href="http://a.com/topic?id=1%EC%9D%B4%EB%9D%BC%EB%8A%94">http://a.com/topic?id=1이라는</a> url이 있다. 여기서 http는 프로토콜이라고 부르고, a.com은 domain이고, topic은 path라고 부른다. 그리고 id=1를 query string이라고 부른다.</p>
<h1 id="⭐query객체의-사용법">⭐query객체의 사용법</h1>
<p><img src="https://velog.velcdn.com/images/ziwon_c/post/896fe6e5-3920-4742-a84b-5b90365509f8/image.png" alt="">
위와 같이 만약 url의 쿼리스트링이 id=1&amp;name=jiwon이라면 res.send(req.query.id+&#39;.&#39;+req.query.name)라는 명령어를 사용하면 된다. 
<img src="https://velog.velcdn.com/images/ziwon_c/post/d4a430ad-b89b-497e-8ac9-a494b28b2256/image.png" alt="">
위의 코드는 선택한 링크에 따라서 다른 url의 내용을 띄워준다.</p>
<p>오늘은 간단하게 query객체를 사용 방법에 대해 공부를 해보았다. url의 구조에 대해 더 자세히 알게 되었고, query객체를 사용하여 query string를 다르게 할 수도 있는 게 신기했다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Node.js] 템플릿 엔진]]></title>
            <link>https://velog.io/@ziwon_c/Node.js-%ED%85%9C%ED%94%8C%EB%A6%BF-%EC%97%94%EC%A7%84</link>
            <guid>https://velog.io/@ziwon_c/Node.js-%ED%85%9C%ED%94%8C%EB%A6%BF-%EC%97%94%EC%A7%84</guid>
            <pubDate>Mon, 30 Jan 2023 12:36:03 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/488bb7e8-2f66-4dd4-903b-bfdfce9cd92e/image.png" alt=""></p>
<h1 id="⭐템플릿-엔진이란">⭐템플릿 엔진이란?</h1>
<p>템플릿 엔진은 템플릿 양식과 특정 데이터 모델에 따른 입력 자료를 합성하여 결과 문서를 출력하는 소프트웨어 또는 소프트웨어 컴포넌트를 말한다.</p>
<p>오늘은 템플릿 엔진을 이용하여 간단한 문법으로 웹페이지를 만드는 것을 해보았다. 나는 Pug라는 Node Express Template Engine를 이용하였다. Pug의 장점은 간단하게 표현해 가독성이 좋고, 마크업 문법보다 코드량이 적어 생산성이 좋아진다. 그리고 JS 연산 결과를 쉽게 보여줄 수 있다. 원래 Pug는 Jade라는 이름을 가지고 있었지만, 상표권에 있는 이름이였기 때문에 Pug라는 이름으로 바뀌었다. 확장자도 Pug로 적어줘야 한다. 난 Jade로 적었다가 제대로 실행이 되지 않아서 구글링을 통해 Pug로 바뀐 것을 알게 되었다.
<img src="https://velog.velcdn.com/images/ziwon_c/post/2bec0524-d945-4fa1-8e27-9b7a043aad5c/image.png" alt="">
Pug를 설치하는 명령어는 npm install pug --save이다.</p>
<h1 id="⭐템플릿-엔진-문법">⭐템플릿 엔진 문법</h1>
<p><img src="https://velog.velcdn.com/images/ziwon_c/post/84f9da7b-861a-4ad8-aa4a-aef76724fcc1/image.png" alt="">
Pug의 문법은 html에 닫는 태그가 없고, 들여쓰기한 이후에 공백까지가 태그로 된다. 태그 사이가 아닌 태그의 속성으로 넣으려면 ( )괄호를 사용한다. 여러 줄을 입력할 때 ( | )로 작성한다.
<img src="https://velog.velcdn.com/images/ziwon_c/post/6eceda73-acae-4a52-a6f4-4bca0589b528/image.png" alt="">
실행을 하게되면 이러한 화면이 나오게 된다.
오늘은 템플릿 엔진을 써보았다. 문법이 간단하고 편리해 신기했고, Jade가 Pug로 바뀌었단 것을 알게되어 어리둥절한 마음도 있었다. 문법이 간단해서 쉽고 재미있었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Node.js]  throw er; // Unhandled 'error' event 에러]]></title>
            <link>https://velog.io/@ziwon_c/Node.js-throw-er-Unhandled-error-event-%EC%97%90%EB%9F%AC</link>
            <guid>https://velog.io/@ziwon_c/Node.js-throw-er-Unhandled-error-event-%EC%97%90%EB%9F%AC</guid>
            <pubDate>Sun, 29 Jan 2023 12:17:05 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ziwon_c/post/02e52671-9ebd-4dd2-9322-5d6d3a069e3e/image.png" alt=""></p>
<h1 id="에러">에러</h1>
<p>app.js를 실행하던 도중에 이러한 에러를 마주하게 되었다.
<img src="https://velog.velcdn.com/images/ziwon_c/post/15a112cf-317f-4c6c-a167-fa5cf7390e93/image.png" alt="">
원인은 기존에 node app.js 프로세스가 기실행 중일 경우에 port끼리의 충돌 발생으로 인해 프로세스가 정상 실행되지 않는 상태가 된 것이다.</p>
<h1 id="해결방법">해결방법</h1>
<p>해결방법은 cmd창에 들어가서 netstat -ano라는 명령어를 친다.
<img src="https://velog.velcdn.com/images/ziwon_c/post/48c7345e-5169-4ac4-a0c4-d206f23903ef/image.png" alt="">
그럼 지금 사용 중인 포트들이 뜨게 된다. 그 다음 로컬 주소에서 꺼야할 포트번호를 찾고 그 포트번호의 PID를 사용해 taskkill /f /pid [PID 번호]라는 명령어를 치면 프로세스가 종료되게 된다.
<img src="https://velog.velcdn.com/images/ziwon_c/post/831894be-0342-4798-89cd-0575f245f58c/image.png" alt="">
오늘은 js를 실행하던 도중 포트 실행 충돌로 인한 에러를 만나게 되었다. 처음엔 명령어들이 다 실행되지 않아 난감했는데 결국 맞는 해결법을 찾아서 에러 해결법을 터득한 것 같아서 뿌듯했다. 나와 동일한 에러를 겪으신 분들이 많으셔서 결국 에러 원인에 대해 파악하고, 스스로 잘 고칠 수 있었다. 주위에서 나와 같은 에러를 겪는 사람이 있다면 다음엔 도움을 줄 수 있다는 사실이 좋았다.</p>
]]></description>
        </item>
    </channel>
</rss>