[42seoul] minishell(2)

ppparkta·2023년 3월 17일
1

42Seoul

목록 보기
7/7

signal

비트연산자

비트 연산자(bitwise operator)
ctrl+C ctrl+\ 등을 처리하기 위해 시그널을 사용할 때, 비트 연산자를 사용해야 해서 정리한다.

비트 연산자설명
&대응되는 비트가 모두 1이면 1을 반환함. (비트 AND 연산)
|대응되는 비트 중에서 하나라도 1이면 1을 반환함. (비트 OR 연산)
^대응되는 비트가 서로 다르면 1을 반환함. (비트 XOR 연산)
~비트를 1이면 0으로, 0이면 1로 반전시킴. (비트 NOT 연산)
<<지정한 수만큼 비트들을 전부 왼쪽으로 이동시킴. (left shift 연산)
>>부호를 유지하면서 지정한 수만큼 비트를 전부 오른쪽으로 이동시킴. (right shift 연산)

기본적으로 스위치를 껐다, 켰다 하는 식으로 생각할 수 있다.

프로세스 종료상태

연습

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

int main(void)
{
	pid_t	pid;
	int		status;

	pid = fork();
	if (pid == 0)
	{
		exit(1);
	}
	else
	{
		wait(&status);
		printf("%d		%d		%d\n", status, status >> 8, status + 128); 
	}
}

출력 결과
768 3 896

종료 상태$?를 통해 확인할 수 있다. 이 숫자는 status를 8비트 시프트 연산했을 때 나온 값이다. 위의 연습 예제로 볼 때 exit(1)을 하면 status에 768이 들어가게 되고, 이 값을 다시 8비트 시프트 연산 하면 원래 의도한 값인 3이 출력된다.

8비트 연산을 수행하기 때문에 status가 256보다 작을 경우, 8비트 시프트 연산을 수행하면 값이 0이 된다.

그러나 실제로 $?를 통해 종료상태를 확인했을 때 status가 2일 때 출력되는 종료상태는 '130'이다.

status가 3일 때 출력되는 종료상태는 131이다.

이처럼 status가 256보다 작은 경우, 8비트 시프트 연산을 수행하면 값이 0이 된다. 그러나 실제 터미널에서 출력되는 값은 status에 128을 더한 값이다.

minishell에서 256보다 작은 status가 쓰이는 경우는 2와 3 두가지 경우가 있다.

따라서 status의 값을 연산할 때 2와 3인 경우의 예외처리를 해야 한다.

wait할 때 참고해서 exit_status 수정하기

ctrl + C

ctrl C handling

#include <termios.h>

...

term.c_lflag &= ~(ECHOCTL);
tcsetattr(STDIN_FILENO, TCSANOW, &term);

기존 ctrl + C를 누르면 진행중인 작업이 종료된다. signal handler로 새로운 리드라인을 생성해도 ^C 문자열은 사라지지 않았다.

ctrl + C 신호를 받았을 때의 출력을 무시하기 위해서 이 코드를 작성했다.

term이라는 객체에 담긴 플래그를 모두 끄기 위해서 모든 스위치가 켜진 수에 ~ 연산자를 사용했다.

해당 값을 기존의 플래그에 적용하기 위해 & 연산자를 사용했다.

ctrl + D

이 부분은 시그널로 처리하지 않고 readline으로 읽어온 값이 NULL이라면 exit을 실행시켰다.

profile
겉촉속촉

0개의 댓글