var Group = new Schema({
  "group": [{
    tag: String,
    name: String
  }]
})

위와 같은 스키마가 있을 때 find를 통해 같은 tag 값을 갖는 리스트를 얻고 싶을 때 다음과 같은 query를 작성할 수 있다.

Group.find({group: {$elemMatch : {tag: tag}}})

$elemMatch를 통해 group 배열 안에 있는 {tag: tag}에 해당하는 도큐먼트가 있다면 데이터를 찾아내 리스트로 출력한다.


$in 이 좀 헛갈렸는데 $in은 해당 키 값에 해당하는 value 값들 중에서 일치하는 documents를 찾는다.

이게 뭔 차이냐먼.. 내 생각에는 $in을 사용해보니 계속 parse error 나는 것 보니까 {tag: tag} 를 value로써 인식하지 못하는 것 같다.

$elemMatch를 사용하지 않는 또 다른 방법이 있다.

Group.find({"group.tag": tag})

위 방식은 '.' 으로 path를 지정해서 찾는 경우이다.

어댑터 뷰

화면에 동적으로 변경되는 컨텐츠를 채울 때 사용하는 뷰

리스트 뷰

항목들을 수직 방향의 목록 형태로 보여주는 어댑터 뷰 - 상하 스크롤 가능 - 일반적으로 목록의 한 항목을 선택하여 일정한 작업 수행

생성 방법1 - element

  1. 레이아웃 파일에 ListView element 를 선언한다.

  2. 액티비티 파일에 어댑터를 생성한다.

  3. 생성한 어댑터를 레이아웃 파일에 선언한 ListView 리소스와 연결시킨다.

public class MainActivity extends AppCompatActivity {
  private ListView m_ListView;
  private ArrayAdapter<String> m_Adapter;
 
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
 
    String[] values = {"String1", "String2", "String3"};
 
    m_Adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, values);
 
    m_ListView = (ListView)findViewById(R.id.list);
 
    m_ListView.setAdapter(m_Adapter);
 
    m_ListView.setOnItemClickListener(onClickListItem);
  }
 
  private AdapterView.OnItemClickListener onClickListItem = new AdapterView.OnItemClickListener() {
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
      Toast.makeText(getApplicationContext(), m_Adapter.getItem(position), Toast.LENGTH_SHORT).show();
    }
  };
}

ListView 아이템 터치시 이벤트를 처리할 리스너를 구현해야 한다.

private AdapterView.OnItemClickListener onClickListItem = new AdapterView.OnItemClickListener() {
 
  @Override
  public void onItemClick<AdapterView<?> parent, View view, int position, long id) {
    Toast.makeText(getApplicationContext(), m_Adapter.getItem(position), Toast.LENGTH_SHORT).show();
  }
};

생성 방법2 - ListActivity 상속

  1. 액티비티에 ListActivity를 상속 받는다.

  2. 어댑터를 생성한다.

  3. setListAdapter 라는 ListActivity에 선언한 함수를 사용하여 어댑터를 액티비티에 설정한다.

public class MainActivity extends ListActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
 
        String[] values = {"하스스톤", "몬스터 헌터", "디아블로", "와우", "리니지", "안드로이드", "아이폰"};
 
        // Android에서 제공하는 표준 레이아웃에 String 문자열 하나를 출력하는 layout으로 어댑터 생성
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, values);
 
        // ListView에 어댑터 연결
        setListAdapter(adapter);
    }
 
    @Override
    protected void onListItemClick(ListView l, View view, int position, long id) {
        String item = (String)getListAdapter().getItem(position);
        Toast.makeText(getApplicationContext(), item + " selected", Toast.LENGTH_SHORT).show();
    }
}

직접 AdapterView의 리스너를 선언하여 구현 및 설정하였던 생성방법 1과 달리 ListActivity를 상속받게 되면 아래와 같은 함수를 사용할 수 있다.

setListAdapter(adapter);
 
@Override
protected void onListItemClick(ListView l, View view, int position, long id);

생성 방법 1과 달리 주의 깊게 봐야할?점은 아래의 코드 같다.

super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);


'IT > Android' 카테고리의 다른 글

Popup Menu 생성  (0) 2017.10.23
AlertDialog를 이용하여 RatingBar 띄우기  (0) 2017.10.23
Intent  (0) 2017.10.23
Action Bar  (0) 2017.10.23
Dialog  (0) 2017.10.23

mongodb에서 Date 타입을 사용하다보면 시간 기준이 한국 시간과 다르다는 것을 확인할 수 있다. 한국 시간보다 7시간이 더 늦음을 확인할 수 있다.

Date.UTC() 함수가 있는데 Date.UTC 함수는 현지 시간 대신 국제 표준시(UTC)를 사용한다. 그래서 위 함수를 이용해서 표준 시를 구할 수 있다.

function getCurrentDate() {
  var date = new Date();
 
  var year = date.getFullYear();
  var month = date.getMonth();
  var today = date.getDate();
  var hours = date.getHours();
  var minutes = date.getMinutes();
  var seconds = date.getSeconds();
  var milliseconds = date.getMilliseconds();
 
  return new Date(Date.UTC(year, month, today, hours, minutes, seconds, milliseconds));
}


'IT > Mongodb' 카테고리의 다른 글

서브 도큐먼트 검색 후 값 변경  (0) 2018.02.07
도큐먼트 필드 삭제하기  (0) 2017.12.30
$elemMatch vs $in  (0) 2017.10.31
스키마 모델링 어떻게 해야 하나  (0) 2017.10.21

라이브러리 함수와 시스템 콜 차이

시스템 콜

커널 자원을 사용자가 사용할 수 있도록 미리 만들어 놓은 함수

사용자 모드 -> 시스템 콜 호출 -> 커널모드

라이브러리 함수

사용자가 많이 사용할 것 같은 기능을 미리 함수로 만들어 놓은 것

사용자 모드 -> 라이브러 함수 호출 -> 사용자 모드

차이가 멀까?

//오류 발생 이유: 메모리할당 하지 않음
time_t * cur_time;
 
time(cur_time);
 
printf("%d", (int)cur_time);

포인트 변수에 메모리를 할당하지 않고 사용하면 Segmentation Fault 오류 발생한다.

time_t * cur_time = (time_t *)malloc(sizeof(time_t));

시스템 콜은 커널이 건네주는 정보를 사용자 모드의 프로그램에 받아오려면 반드시 사용자 영역에 메모리를 할당해야 한다.

time_t * cur_time;
 
char * cur_string;
 
cur_string = ctime(cur_time);
printf("%s", cur_string);

하지만 라이브러리 함수는 사용자의 영역의 메모리를 별도로 할당하지 않아도 된다.

오류 처리 결과의 차이점도 있다.

시스템 콜 함수는 오류시 리턴 값은 -1이지만 라이브러리 함수는 오류시 NULL 값을 리턴한다.

'Operator System > Linux' 카테고리의 다른 글

쉘 프로그래밍 간단한 문법  (0) 2017.10.26
프로세스와 생성방법  (0) 2017.10.26
Make  (0) 2017.10.26
파일  (0) 2017.10.26
Compile과 라이브러리  (0) 2017.10.26

쉘이란?

shell은 사용자와 리눅스 사이의 인터페이스를 제공하는 프로그램이다.

리눅스 기본 쉘은 /bin/sh 에 존재한다.

로그인 쉘

사용자가 로그인할 때 실행되는 쉘로서 /etc/passwd 에 로그인 쉘 등록된다.

root:x:0:0:root:/root:/bin/bash

사용자명 : 패스워드 : 사용자 계정 uid : 사용자 계정 gid : 이름 : 홈 디렉토리 : 사용자 계쩡 로그인 쉘

변수

  • Linux 는 대소문자를 구분한다. 모든 변수는 String으로 표현한다.

  • 변수 값 정의는 "="을 사용하며 앞뒤에 공백문자 사용을 금지한다.

  • 변수 값 접근은 변수명 앞에 '$'을 사용한다.

  • 사용자 입력 값을 변수에 할당할 때는 read를 사용한다.

$ read n
5
$ echo $n
5

문법을 알아보자

if

#!/bin/sh
 
read timeofday
 
if [ $timeofday = "yes" ]
then
  echo "Good morning"
elif [ $timeofday = "no"]
then
  echo "Good afternoon"
else
  echo "so so"
fi
 
exit 0

for

#!/bin/sh
 
for foo in bar fud 43
do
  echo $foo
done
 
exit 0

while

#!/bin/sh
 
read trythis
 
while [ "$trythis" != "secret" ]
do
  echo "Sorry, try again"
  read trythis
done
 
exit 0

until

조건이 만족될 때까지 실행 금지. 적어도 한번은 실행

#!/bin/sh
 
until who | grep "$1" > /dev/null
do
  sleep 60
done
 
echo -e '\a'
echo "**** $1 has just logged in ****"
 
exit 0

case

#!/bin/sh
 
read timeofday
 
case "$timeofday" in
  yes) echo "Good morning";;
  no ) echo "Good Afternoon";;
  y ) echo "Good Morning";;
  n ) echo "Good Afternoon";;
  * ) echo "Sorry"
esac
 
exit 0

List

#!/bin/sh
 
touch file_one
 
if [ -f file_one ] && echo "hello"
then
  echo "in if"
else
  echo "in else"
fi
 
exit 0

출력화면

hello
in if

function

#!/bin/sh
 
foo() {
  echo "Function foo is executing"
}
 
echo "scriipt starting"
foo()
echo "script ended"
 
exit 0


'Operator System > Linux' 카테고리의 다른 글

라이브러리 함수와 시스템 콜 차이  (0) 2017.10.26
프로세스와 생성방법  (0) 2017.10.26
Make  (0) 2017.10.26
파일  (0) 2017.10.26
Compile과 라이브러리  (0) 2017.10.26

프로세스

프로세스 구성요소

  • 프로그램 코드

  • 데이터

  • 시스템 메모리를 사용하는 변수

  • 프로세스에서 오픈한 파일 디스크립터

  • 환경변수

프로세스 모델

같은 프로그램을 실행하는 서로 다른 프로세스

  • 프로그램 코드와 라이브러리 코드를 공유하기 때문에 하나의 프로그램에 대해 여러 프로세스가 공유

  • 프로세서 마다 고유 pid 할당

  • 프로그램 카운터 프로세스마다 고유

  • 데이터 공간과 스택공간은 프로세스마다 고유 할당

  • 프로세스가 open한 파일, 환경변수도 프로세스 별로 관리

task

리눅스에서 프로세스를 task라 정의, task_struct 라는 데이터 구조체를 사용하여 표현한다.

  • /usr/src/linux/include/linux/sched.h에 정의

  • 프로세스와 관련된 모든 정보를 정의한 데이터 구조체

  • 운영체제 버전이나 플랫폼에 따라 구조체 내부 변수들이 추가되거나 삭제

struct task_struct {
  volatile long state;
  ...
  pid_t pid;
  ...
}

프로세스 관련 소스 파일

  • kernel/sched.c : 프로세스 스케쥴러

  • kernel/signal : 시그널 처리 함수

  • kernel/fork.c : 프로세스 생성 함수

  • kernel/exit.c : 프로세스 종료 함수

  • fs/exec.c : 프로그램 실행

  • arch/i386/kernel/entry.S : 커널 초기 함수

  • arch/i386/kernel/process.c : architecture 의존 프로세스

PID와 프로세스 테이블

PID

각 프로세서는 프로세스 ID라는 유일한 식별자가 할당된다. 프로세스가 시작되면 할당되지 않은 다음 번호가 자동 할당된다.

프로세스 테이블

현재 메모리에 로딩된 모든 프로세스들에 대한 정보 저장하는 구조체

프로세스들에 대한 정보를 화면에 표시하기 위한 명령어 > ps -ef 또는 ps -ax

프로세스 스케쥴링

리눅스 커널에서는 다음 time slice에 실행할 프로세스를 선발 하기 위해 우선순위 기반의 스케쥴링을 사용한다.

프로세스의 우선 순위는 nice값에 의해 결정된다.

명령어설명
nicenice값을 10 증가
renicenice값을 변경
ps -lnice 값 확인

&을 이용하여 백그라운드 프로세스로 실행할 수 있다.

$ ./test &

프로세스 생성

system

"system" 라이브러리 함수를 사용하여 프로그램 내부에서 다른 프로그램을 실행하여 새로운 프로세스를 생성할 수 있다.

#include <stdlib.h>
int system(const char * string)

예시)

#include <stdlib.h>
#include <stdio.h>
 
int main() {
  printf("Running ps with system\n");
  system("ps ax");
  printf("Done\n");
  exit(0);
}

system 함수는 파라미터로 전달된 명령어 문자열을 실행한 후 종료될때까지 대기한다. 즉, "Running ps with system" 문자열 출력 후 ps ax 명령어를 실행 후 "Done"이라는 문자열이 출력된다.

fork()

현재 프로세스의 이미지 복사.

  • 현재 프로세스의 속성을 대부분 그대로 사용하는 새로운 프로세스를 생성해서 프로세스 테이블에 등록

  • 새로운 프로세스는 현재 프로세스와 동일한 코드를 사용하지만 고유 공간, 환경변수, 파일 디스크립터를 사용한다.

parent process는 wait(&status)를 호출하여 child process의 종료를 기다린다.

printf("pid = %d\n", getpid());
 
pid = fork();
 
switch(pid) {
  case -1:
    perror("fork error");
    exit(1);
  case 0:
    printf("child process\n")
    printf("getpid() = %d\n", getpid());
    printf("pid = %d\n", pid);
  default:
    printf("parent process\n");
    printf("getpid() = %d\n", getpid());
    printf("pid = %d\n", pid);
}
  • 위 코드를 실행시키면 fork함수 호출 전의 getpid() 값은 parent의 getpid()와 같음을 알 수 있다.

  • 하지만 fork() 함수의 반환값으로 얻은 pid는 부모 프로세스에게 새로운 pid를 할당한다. 해서 부모프로세스의 pid 값과 getpid() 값은 다르다는 것을 확인할 수 있다.

  • 자식 프로세스의 getpid() 값은 부모 프로세스의 pid와 같음을 확인할 수 있다. 자식 프로세스는 자신만의 pid를 갖게 되고, ppid는 부모 프로세스의 pid를 가지게 된다. PGID, SID 를 상속받으며, 파일지시자, 시그널등을 상속받는다. 단 파일잠금(lock)와 시그널 팬딩은 상속받지 않는다.

exec()

현재 프로세스의 이미지 변경.

  • fork()는 복사지만, exec()는 새로운 프로그램으로 다시 실행하게 된다.

  • 현재 프로세스가 더 이상 실행되지 않는다.("system"함수와 다름)

char * const ps_argv[] = {"ps", "ax", 0};
 
char * const ps_envp[] = {"PATH=/bin:/usr/bin", "TERM=console", 0};
 
execl("/bin/ps", "ps", "ax", 0);
execlp("ps", "ps", "ax", 0);
execle("/bin/ps", "px", "ax", 0, ps_envp);
execv("/bin/ps", ps_argv);
execvp("ps", ps_argv);
execve("/bin/ps", ps_argv, ps_envp);

위 코드는 아래의 exec 함수의 접미어에 따라 전달 방법을 달리한 예시이다.

  • l : 명령어 인자들을 리스트 형태로 전달

  • v : 명령어 인자들을 문자열 배열 형태로 전달

  • p : 명령어 파일명을 전달. 파일탐색경로는 PATH 환경변수 사용

  • e : 명렁어 실행에 사용할 환경변수 전달

예시)

#include <stdlib.h>
#include <stdio.h>
 
int main() {
  printf("Running ps with system\n");
  execlp("ps", "ps", "ax", 0);
  printf("Done\n");
  exit(0);
}

위 코드는 system 함수와 비교해서 보면, system 함수와 달리 execlp 함수가 호출됨으로 인해 프로세스 이미지가 변경되어 "Done"문자열을 출력하지 않고 ps ax 쉘을 실행시키고 종료한다.

프로세스 종료 대기

wait 함수는 자식 프로세스중 하나가 종료할 때까지 부모 프로세스를 대기시킨다.

  • 종료된 자식 프로세스의 pid를 반환

  • 종료된 자식 프로세스의 상태정보는 "stat_loc"에 저장.

#include <sys/types.h>
#include <sys/wait.h>
 
pid_t wait(int * stat_loc);
if(pid != 0) {
  int stat_val;
  pid_t child_pid;
 
  child_pid wait(&stat_val);
 
  printf("Child has finished: PID = %d\n", child_pid);
 
  if(WIFEXITED(stat_val))
    printf("Child exited with code %d\n", WEXITSTATUS(stat_val));
  else
    printf("Child terminated abnormally\n");
 
  exit(exit_code);
}
매크로정의
WIFEXITED자식 프로세스가 정장석으로 종료하면 0이 아닌 값을 리턴
WEXITSTATUSWIFEXITED가 0이 아니면, child exit code 값을 리턴
WIFSIGNALED자식이 어떤 신호로 인해서 종료되었다면 0이 아닌 값을 리턴
WTERMSIGWIFSIGNALED가 0이 아니면, signal number 를 리턴
WIFSTOPPED자식 프로세스가 정지되었다면 0이 아닌 값을 리턴
WSTOPSIGWIFSTOPPED가 0이 아니면, signal number 를 리턴

좀비 프로세스

  • 부모 프로세스가 비정상 종료하면 운영체제에 의해 init 프로세스(PID = 1) 가 자식 프로세스들의 부모 프로세스가 된다.

  • 좀비 프로세스는 init 프로세스에 의해 제거될 때까지 프로세스 테이블에 남겨진다.


'Operator System > Linux' 카테고리의 다른 글

라이브러리 함수와 시스템 콜 차이  (0) 2017.10.26
쉘 프로그래밍 간단한 문법  (0) 2017.10.26
Make  (0) 2017.10.26
파일  (0) 2017.10.26
Compile과 라이브러리  (0) 2017.10.26

make

여러 개의 파일로 구성된 소프트웨어를 개발하는 도구

make 기능

  • 수정된 파일들을 필요에 따라 다시 컴파일

  • 소스 파일들의 컴파일 순서를 결정

  • 컴파일한 소프트웨어를 원하는 디렉토리에 설치

  • 메뉴얼 페이지를 작성

make 사용법

실행방법

  • Makefile이 있는 디렉토리에서 'make'를 실행

옵션

  • -k : 컴파일 과정에서 에러가 발생해도 무시하고 계속 진행

  • -n : 작업할 내용을 화면에 출력

  • -f : makefile 대신 사용할 파일을 지정

파라미터

  1. target

  • 타겟명이 파라미터로 지정되면 지정된 타겟을 생성한다.

  • 타겟 명이 지정되지 않으면 makefild에 나열된 타겟들 중에서 첫 번째 타겟을 생성한다.

  • 기본적으로 all 타겟을 첫 번째 타겟으로 설정하고 다른 타겟들은 all target을 만들기 위한 의존 타겟들로 정의 나열

  1. rule

  • 최종 응용 프로그램을 구성하는 각 파일들이 프로그램 소스파일들과 어떻게 관련되어 있는지를 설명

  1. prerequisites

  • 타겟을 만들 때 필요한 파일들의 리스트

  1. Recipe

  • prerequisites 를 사용하여 타겟을 만드는 방법을 기술

정의 방법

# simple Makefile
myapp: main.o 2.o 3.o
  gcc -o myapp main.o 2.o 3.o
 
main.o: main.c a.h
  gcc -c main.c
 
2.o: 2.c a.h b.h
  gcc -c 2.c
 
3.o: 3.c b.h c.h
  gcc -c 3.c

Macro

문법

  • MACRONAME = value,

사용법

  • (MACRONAME) or{MACRONAME}

Automatic Variable

  • $@ : 현재 타겟 이름

  • $* : 확장자를 제거한 타겟 이름

  • $< : 첫번째 prerequisites 이름

  • $^ : 전체 prerequisites 리스트

  • $? : 현재 타겟 생성 이후에 수정된 prerequisites 리스트

OBJS = hello.o hello_msg1 hello_msg2 hello_msg3
 
hello:$(OBJS)
  gcc -o $@ $(OBJS)
 
hello.o:hello.c
  gcc -c $<
 
hello_msg1.o:hello_msg1.c
  gcc -c $^[0]
 
hello_msg2.o:hello_msg2.c
  gcc -c $*.c

Internal Macro

명령어 앞에 추가되는 특수 문자

  • '-' : 명령어 실행시 발생하는 에러 무시

  • '@' : 명렁어 실행 전에 화면에 명령어를 출력하지 않음

Phony Target

  • Phony Target 이란 타게시름이 실제 파일이름이 아닌 타겟을 말한다.

  • Phony target 지정 방법은 명시적으로 특수 타겟인 ".PHONY"을 사용하여 명시적으로 지정한다.

사용 이유

  • 같은 이름의 파일과 충돌하는 것을 피하기 위한 목적

  • Make가 phony target을 위한 rule 탐색을 하지 않기에 성능 향상 목적

clean:
  -rm main.o 2.o 3.o

'-'를 이용하여 main.o 2.o 3.o를 에러를 무시하고 rm 을 수행

$ make clean

쉘에서 make clean을 주어 makefile 에 정의한 Phony Target을 지정

'Operator System > Linux' 카테고리의 다른 글

쉘 프로그래밍 간단한 문법  (0) 2017.10.26
프로세스와 생성방법  (0) 2017.10.26
파일  (0) 2017.10.26
Compile과 라이브러리  (0) 2017.10.26
환경변수  (0) 2017.10.26

파일

파일이란?

파일은 데이터를 저장하는 수단을 말하는 추상적인 개념.

파일 시스템

데이터 저장매체에 데이터를 저장하고 관리하는 방법.

디바이스 파일

디바이스 파일이란 입출력 디바이스를 표현하는 특수 파일로 /dev 디렉토리에 저장된다.

  • /dev/console : 시스템 콘솔

  • /dev/tty : 프로세스의 터미널 논리 디바이스

  • /dev/null : null 디바이스로 이 디바이스에 쓰여진 모든 데이터는 사라진다.

  • /dev/zero : 0으로 채워진 파일을 만들 때 사용

저수준 파일 함수

시스템 콜을 통한 접근으로 파일 디스크립터를 사용한다.

파일 디스크립터란 파일 접근에 사용되는 정수 값으로 0(입력), 1(출력), 2(에러)를 의미한다.

#include <fcntl.h>
#include <sys/types.h>
#incldue <sys/stat.h>
 
int open(const char * path, int oflags);
 
int open(const char * path, int oflags, mode_t mode);
  • oflags 는 O_RDONLY, O_WRONLY, O_CREAT등이 있다.

  • mode는 S_IRUSR, S_IWUSR 등이 있다.

#include <unistd.h>
 
int close(int fildes);
#include <unistd.h>
 
size_t read(int fildes, void * buf, size_t nbytes);
#include <unistd.h>
 
size_t write(int fildes, const void * buf, size_t nbytes);

고수준 파일 함수

표준 라이브러리 함수 호출을 통한 접근으로 파일 포인터(file stream 이용)를 사용한다.

#include <sys/stat.h>
 
int mkdir(const char * path, mode_t mode);

디렉토리 생성

#include <unistd.h>
int rmdir(const char * path);

디렉토리 삭제

#include <unistd.h>
int chdir(const char * path);

디렉토리 변경

#include <unistd.h>
char * getcwd(char * buf, size_t size);

현재 디렉토리명 반환

#include <sys/types.h>
#include <dirent.h>
 
DIR * opendir(const char * name);

디렉토리 스트림 생성

 
#include <sys/types.h>
#include <dirent.h>
 
struct dirent * readdir(DIR * dirp);

디렉토리 읽기

#include <sys/types.h>
#include <dirent.h>
 
vodi seekdir(DIR * dirp, long int loc);

디렉토리 엔트리 포인트를 loc 위치로 이동

#include <sys/types/h>
#include <dirent.h>
 
int closedir(DIR * dirp);

디렉토리 스트림 해제

파일 및 디렉토리 판별

#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
 
void printdir(char * dir, int depth) {
  DIR * dp;
  struct dirent * entry;
  struct stat statbuf;
 
  if((dp = opendir(dir)) == NULL) {
    fprintf(stderr, "cannot open directory: %s\n", dir);
  }
 
  chdir(dir);
 
  while((entry = readdir(dp)) != NULL) {
    lstat(entry->d_name, &statbuf);
    if(S_ISDIR(statbuf.st_mode)) {
      if(strcmp(".", entry->d_name) == 0 ||
        strcmp("..", entry->d_name) == 0) continue;
 
      printf("%*s%s\n", depth, "", entry->d_name);
 
      printdir(entry->d_name, depth+4);
    } else {
      printf("%*s%s\n", depth, "", entry->d_name);
    }
  }
 
  chdir("..");
  closedir(dp);
}

설명 :

opendir을 하여 읽기에 성공하였으면 dp NULL이 아닌 값을, 실패하면 NULL 값을 얻는다.

dp에는 해당 디렉토리에 대한 스트림에 대한 정보가 들어있다.

readdir(dp)를 통해 해당 디렉토리에 대한 파일정보를 struct dirent * 구조체인 entry에 넣는다.

lstat은 링크에 대한 정보를 얻는 함수로 entry->d_name이 가리키는 파일 정보를 문자열 배열에다가 저장한다.

S_ISDIR(statbuf.st_mode) 함수로 디렉토리 여부 검사를 한다.

procfs

디바이스 드라이버나 운영체제 커널에 대한 실시간 정보를 제공해주는 특수 파일 시스템이다.

'Operator System > Linux' 카테고리의 다른 글

쉘 프로그래밍 간단한 문법  (0) 2017.10.26
프로세스와 생성방법  (0) 2017.10.26
Make  (0) 2017.10.26
Compile과 라이브러리  (0) 2017.10.26
환경변수  (0) 2017.10.26

+ Recent posts