Su quale terminale virtuale è in esecuzione un determinato processo X?


8

All'avvio di X, cerca il VT inutilizzato più basso e si attacca ad esso. Il mio problema è che quando ci sono diversi processi X in esecuzione, devo essere in grado di identificare quale è quello attualmente attivo.

Questa è una domanda * BSD, perché su Linux è facile: X imposta il suo terminale di controllo su ttyN, o, su distribuzioni molto vecchie, è specificato sulla riga di comando come vtN. Quindi, sto eseguendo un servizio e vedo che il VT attualmente attivo è tty7, e ci sono due server X in esecuzione, è facile dire quale corrisponde al terminale corrente. (Questo è un caso ragionevole: forse l'utente ha usato la funzionalità 'switch user' di GNOME / KDE o ha eseguito due server usando startx.) Un'applicazione di esempio che potrebbe voler seguire il server X attivo è x11vnc(che è biforcuta dal software che sto sviluppando ).

Su FreeBSD, tuttavia, il terminale di controllo non ti dice nulla. Quando X viene avviato da ttyv1, questo rimane il terminale di controllo.

Aggiornare

Ho fatto la dovuta diligenza e ho letto il codice X. Dopo un po 'di caccia in giro, ora mi è più chiaro cosa sta succedendo.

In lnx_init.c , il server X fa setsiduna nuova sessione per se stesso, quindi apre un fd ttyNper eseguire subito uno VT_ACTIVATEioctl su di esso. Piuttosto standard; l'apertura di fd a un terminale senza processo di controllo da un processo senza terminale di controllo associa i due e il server mantiene aperto fd, quindi è garantito che il terminale rimarrà il terminale di controllo per il server X.

Ora, in bsd_init.c , l'apertura di fd su tty da utilizzare come framebuffer non lo rende un terminale di controllo (e in effetti, senza setsid, BSD Xserver avviato da xinitttyv2 manterrà ttyv2 come suo ctty!).

Domanda ulteriormente aggiornata e ripulita il 09-04-2012.

Risposte:


3

C'è un modo più generale. Su tutte le piattaforme con terminali virtuali, inclusi linux e BSD, Xserver mantiene un fd aperto sul terminale su cui è in esecuzione. Su Linux, rimane una buona soluzione per verificare il terminale di controllo del processo X per distinguere tra più processi X (utilizzare il settimo campo di /proc/<..>/stat). Più in generale, però, guarda l'elenco delle fds aperte del processo X, e necessita solo di un semplice filtro per uscire dal terminale su cui Xserver è in esecuzione. (Sfortunatamente, ottenere l'elenco di open fds è di nuovo dipendente dalla piattaforma ...) Per sysctlpiattaforme come BSD, il codice sarà simile a questo, oltre a una gestione degli errori:

int ttyByOpenFds(int curPid) {
    int ctl[4] = { CTL_KERN, KERN_PROC, KERN_PROC_FILEDESC, curPid };
    size_t sizeGuess = 50*sizeof(kinfo_file);
    char* buf = malloc(sizeGuess);
    int rv = sysctl(ctl, 4, buf, &sizeGuess, 0, 0);
    if (rv < 0 && errno == ESRCH) return 0;
    else if (rv < 0 && errno == ENOMEM) { /* try again */ }
    else if (rv < 0) throw SystemException("unexpected error getting args", errno);

    char* position = buf;
    while (position < buf + sizeGuess) {
      kinfo_file* kfp = reinterpret_cast<kinfo_file*>(position);
      position += kfp->kf_structsize;
      if (kfp->kf_type != KF_TYPE_VNODE) continue;
      if (kfp->kf_vnode_type != KF_VTYPE_VCHR) continue;
      if (kfp->kf_fd < 0) continue;
      char* name = devname(kfp->kf_un.kf_file.kf_file_rdev, S_IFCHR);
      if (!name) continue;
      unsigned int ttynum = 0;
      if (sscanf(name, "ttyv%u", &ttynum) != 1) continue;
      if (ttynum < 8 && kfp->kf_fd <= 2) continue; // stderr going to a console
      return ttynum;
    }
    return 0;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.