본문 바로가기
Computer Science/UNIX & Linux

[UNIX/Linux] ep7+) 프로세스 생성과 실행 함수 실습

by 클레어몬트 2024. 10. 22.

(ex1_argc.c 파일)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>

char* usage = "Usage : Directory Suffix\n";

int my_double_ls(const char*, char*);
int match(const char*, const char*);

int main(int argc, char** argv) {
    if (argc != 3) {
        fprintf(stderr, usage);
        exit(1);
    }

    my_double_ls(argv[1], argv[2]);
    exit(0);

    return 0;
}

int my_double_ls(const char* name, char* suffix) {
    struct dirent* d;
    DIR* dp;

    if ((dp = opendir(name)) == NULL) {
        return -1;
    }
    while (d = readdir(dp)) {
        if (d->d_ino != 0) {
            printf("%s\n", d->d_name);
        }
        if (match(d->d_name, suffix)) {
            printf("***Matched %s\n", d->d_name);
        }
    }
    closedir(dp);
    return 0;
}

int match(const char* s1, const char* s2) {
    int diff = strlen(s1) - strlen(s2);

    if (strlen(s1) > strlen(s2)) {
        return (strcmp(&s1[diff], s2) == 0);
    }
    else {
        return 0;
    }
}

 

 

ex1. 현재 디렉터리에서. c로 끝나는 모든 파일들을 출력하는 프로그램을 exec 시스템 호출을 이용하여 실행하라

 

(In ex1.c)

    argv[0] = “ex1_argc”; argv[1] = “.”; argv[2] = “.c”; argv[3] = NULL;

    execv(“./ex1_argc”, argv)

    .....

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    char* argv[4];

    printf("--> Before exec function\n");
    argv[0] = "ex1_argc";
    argv[1] = ".";
    argv[2] = ".c";
    argv[3] = NULL;

    if (execv("./ex1_argc", argv) == -1) {
        perror("execve");
        exit(1);
    }
    printf("--> After exec function\n");

    return 0;
}

현재 디렉터리의 .c 파일을 찾아 출력

 

 

 

ex2. 부모 프로세스에서 개방된 파일은 자식 프로세스에서도 개방되어 있고, 자식은 각 파일과 연관하여 자신의 파일 기술자(fd)의 복제를 유지하고 있다. 이와 관련된 사항을 확인하는 코드를 다음과 같은 차례로 작성하라

- 데이터 파일을 open

- 10bytes을 읽고, 현재 파일 위치를 출력

- fork() 호출

- 자식은 10bytes를 읽고, 현재 파일 위치를 출력

- 부모는 wait((int*)0)로 자식이 종료하기를 기다린 후, 현재 파일 위치를 출력

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int printpos(const char* string, int filedes);

int main() {
	int fd;
	int nread;
	pid_t pid;
	char buf[10];

	if ((fd = open("testdata", O_RDONLY)) == -1) {
		perror("open failed");
	}

	read(fd, buf, 10);

	printpos("Before fork", fd);

	switch(pid = fork()) {
	case -1:
		perror("fork failed");
		break;
	case 0:
		printpos("Child before read", fd);
		read(fd, buf, 10);
		printpos("Child after read", fd);
		close (fd);
		break;
	default:
		wait((int*)0);
		printpos("Parent after wait", fd);
		if ((nread = read(fd, buf, 10)) <= 0) {
			perror("file read error");
		}
	}

	return 0;
}

int printpos(const char* string, int filedes) {
	off_t pos;
	if ((pos = lseek(filedes, 0, SEEK_CUR)) == -1) {
		perror ("lseek failed");
	}
	printf("%s:%ld\n", string, pos);
}

fork() 호출 시 파일 디스크립터(fd)의 상태가 자식과 부모 프로세스에서 공유된다

 

  • Before fork: 부모 프로세스가 fork() 호출 전, read()를 한 번 수행하여 파일 포인터가 10바이트만큼 이동한 상태를 출력
  • Child before read: 자식 프로세스는 fork() 이후에도 부모와 동일한 파일 디스크립터(fd)를 사용하고, 같은 파일 포인터(fp) 위치(10바이트)를 공유
  • Child after read: 자식 프로세스가 10바이트를 더 읽은 후, 파일 포인터(fp) 위치가 20바이트로 이동.
  • Parent after wait: 부모 프로세스는 자식이 종료한 후에 20바이트 위치에서부터 추가로 파일을 읽으려 시도.

 

 

 

 

 

 

참고 및 출처: 시스템 프로그래밍 리눅스&유닉스(이종원)