백그라운드에서 "gdbserver"를 시작하는 방법은 무엇입니까?

백그라운드에서 "gdbserver"를 시작하는 방법은 무엇입니까?

장치에서 gdbserver를 실행할 때(좋다 gdbserver :2345 myapp), gdbserver는 터미널을 완전히 차단합니다. 앰퍼샌드를 추가하거나 누르면 백그라운드에서 실행되지 &않습니다 . ^z나는 또한 확인했습니다: 쿠분투에서도 재현 가능합니다.

쉘 명령을 사용해야 하는 이유는 다음과 같습니다.gdbserver를 통해 이를 실행하는 방법을 모르겠습니다.나는 달리기 후에 마비된 느낌을 받았다.

답변1

이것은 OP에서 작동하는 것 같습니다.

gdbserver :2345 ls > /dev/null 2>&1 &

그 이유는 프로그램이 데몬화되면 STDIO 0, 1, 2가 모두 닫히기 때문이라고 생각합니다. 다음에 열리는 IO는 0이 됩니다. 프로그램이 printf 또는 scanf와 같은 항목에 0,1 또는 2를 사용하려고 하면 잘못된 IO 또는 닫힌 IO에 대해 작동합니다. 예를 들어 데몬화된 경우 소켓은 0(STDIN)에서 열리고 printf가 호출되면 열리지 않은 FD에 쓰기 때문에 프로그램이 중단됩니다.

답변2

나는 실제로 쉘을 포크하는 방법을 찾지 못했습니다. 연결을 유지해야 할 이유가 너무 많습니다. 나는 이후에 실행하는 모든 명령을 완전히 분기하는 아주 작은 C 프로그램을 작성했습니다.

----- daemonize.c

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>

int main(int argc, char *argv[]) {
    int i;
    // int reterr;
    pid_t pid, sid;

    //Fork the Parent Process
    pid = fork();

    if (pid < 0) { exit(EXIT_FAILURE); }

    //We got a good pid, Close the Parent Process
    if (pid > 0) { exit(EXIT_SUCCESS); }

    //Change File Mask
    umask(0);

    //Create a new Signature Id for our child
    sid = setsid();
    if (sid < 0) { exit(EXIT_FAILURE); }

    //Change Directory
    //If we cant find the directory we exit with failure.
    if ((chdir("/")) < 0) { exit(EXIT_FAILURE); }

    //Close Standard File Descriptors
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);

    //----------------
    //Main Process
    //----------------
    for(i=0; i < argc - 1; i++) {
        argv[i]=argv[i+1];
    }
    argv[argc-1] = '\0';
    execv(argv[0], argv);
    //reterr = execv(argv[0], argv);
    //printf("execv failed with '%s'\n", strerror(errno));

    //Close the log
    closelog ();
}

--- 파일 생성

CXX = gcc

# Implicit rules needed to build .o files and Metaobject stuff (_m.o)
.SUFFIXES: .c .o .h

.c.o:
    $(CXX) -c $(XTRA_INCL)   $< -o $@

OBJECTS = daemonize.o 
daemonize: $(OBJECTS)
    $(CXX) -o $@ -pipe -O2 $(OBJECTS) $(RPATH_XT)
    strip --strip-unneeded $@

clean:
    @rm -f core *.o *_m.* *.bak *.elf

답변3

내 멘토 중 한 명인 Roe Peterson은 모든 항목이 FD에 다시 연결되는 것을 방지하기 위해 항상 null을 반복하여 IO를 닫습니다. 나는 데몬이 이런 식으로 더 안정적이라는 것을 알았습니다.

daemonize()
{
        int fd1,fd2,fd3;

        signal(SIGCLD,SIG_IGN);

        if(fork()) {
                setpgid(getpid(),getpid());
                exit(0);
        }
        setpgid(0,0);

        fd1 = open("/dev/null",O_RDWR);
        fd2 = open("/dev/null",O_RDWR);
        fd3 = open("/dev/null",O_RDWR);


        close(0); dup(fd3);
        close(1); dup(fd3);
        close(2); dup(fd3);
        close(fd3);
        close(fd2);
        close(fd1);
}

관련 정보