İşlerin Başlatılması
Önceki Bir İş Denetim kabuğunun Gerçeklenmesi Sonraki
İşlerin Başlatılması
Kabuk kendi denetim uçbiriminde iş denetimi uygulamak için sorumluluğu aldıktan sonra, kullanıcı tarafından yazılan komutlara yanıt olarak işleri başlatabilir.
Bir süreç grubunda süreçleri oluşturmak için Süreç Oluşturma Kavramları bölümünde açıklandığı gibi fork ve exec işlevleri kullanılabilir. Çok sayıda alt süreç karışık olduğundan, ister istemez, bazı şeyler biraz karmaşıklaşır, bu bakımdan bunları doğru sırada yapmak önem kazanır. Aksi takdirde istenmeyen yarış koşulları ortaya çıkabilir.
Süreçlerle ilgili ata-çocuk birliktelik ağacının yapılanmasında yerine göre iki seçimden birini kullanabilirsiniz. Ya, süreç grubundaki tüm süreçleri kabuk sürecinin çocukları yaparsınız ya da, süreç grubundaki bir süreci gruptaki diğer süreçlerin atası yaparsınız. Tıpkı, bu oylumun tamamındaki örnekleri basit bir kabuk yazılımının parçaları olarak vermemiz gibi, çünkü bu, bazı şeylerin muhasebesini yapmayı koloylaştırıyor.
Her süreç çatallandığında, setpgid çağrısı ile kendini yeni süreç grubuna koymalıdır; bkz. Süreç Grubu İşlevleri. Süreç grubundaki ilk süreç süreç grubunun lideri haline gelir ve onun süreç kimliği de süreç grup kimliği haline gelir.
Kabuk buna ek olarak kendi alt süreçlerinini yeni süreç grubuna koymak için her süreç için ayrı ayrı setpgid çağrıları yapmalıdır. Olası bir zamanlama sorunu nedeniyle bunun böyle olması gerekir: her alt süreç kendi alt sürecini çalıştırmaya başlamadan önce süreç grubuna konulmak ve dolayısıyla kabuk çalışamaya devam etmeden önce grubundaki alt süreçlerini bağlamak zorundadır. Eğer hem kabuk hem de alt süreci setpgid çağrısı yaparsa, hangi sürecin bunu önce yaptığına bakılmaksızın işler olması gerektiği gibi yürür.
Eğer iş bir önalan işi olarak başlatılmışsa, yeni süreç grubunun ayrıca tcsetpgrp kullanılarak denetim uçbiriminde önalana konulması gerekir. Tekrar, yarış koşullarından kaçınmak için bu işlem, hem kabuk tarafından hem de kabuğun alt süreçlerinin her biri tarafından yapılmalıdır.
Bundan sonra, her alt süreç kendi sinyal eylemlerini sıfırlamalıdır.
İlklendirme sırasında, kabuk süreci kendini iş denetim sinyallarini yoksaymaya ayarlamalıdır; bkz. Kabuğun İlklendirilmesi. Sonuç olarak, bir miras olarak her alt süreç oluşturulduğunda bu sinyalleri yoksayacaktır. Bu kesinlikle istenmeyen bir durumdur, bu bakımdan kabuğun her alt süreci çatallandığında bu sinyaller SIG_DFL'a yani öntanımlı haline getirmelidir.
Kabuklar bu uzlaşımlara uyduğundan, uygulamalar kendini çalıştıran süreçten bu sinyalleri doğru eylemlerle aldıklarını kabul edebilirler. Fakat her uygulamanın durdurma sinyallerinin işlenmesini bozmama sorumluluğu vardır. SUSP karakterinin normal yorumunu iptal eden uygulamalar, kullanıcıya işi durdurmak için başka mekanizmalar sunmalıdır. Kullanıcı bu mekanizmayı çalıştırdığında yazılım sadece kendi sürecinde değil, kendi süreç grubuna da bir SIGTSTP sinyali göndermelidir. Bkz. Başka Bir Sürece Sinyal Gönderme.
Son olarak, her süreç normal yolla exec çağrısı yapmalıdır. Bu ayrıca standart girdi ve çıktı kanallarının yönlendirilmesinde önemlidir. Bunun nasıl yapılacağı Tanıtıcıların Çoğullanması bölümünde açıklanmıştır.
Örnek kabuk yazılımından, bir uygulamayı çalıştırmakla yükümlü bir işlev aşağıda gösterilmiştir. Kabuk tarafından çatatallandıktan hemen sonra her alt süreç tarafından bu işlev çalıştırılır ve işlev asla dönmez.
void
launch_process (process *p, pid_t pgid,
                int infile, int outfile, int errfile,
                int foreground)
{
  pid_t pid;

  if (shell_is_interactive)
    {
      /* Süreci süreç grubuna koy ve uygunsa uçbirimi
         süreç grubuna ver. Olası yarış koşullarının oluşmasını
         engellemek için hem kabuk hem de her alt süreç
         tarafından bu yapılmalıdır.  */
      pid = getpid ();
      if (pgid == 0) pgid = pid;
      setpgid (pid, pgid);
      if (foreground)
        tcsetpgrp (shell_terminal, pgid);

      /* İş denetim sinyallerini öntanımlı eylemlerine ayarlayalım..  */
      signal (SIGINT, SIG_DFL);
      signal (SIGQUIT, SIG_DFL);
      signal (SIGTSTP, SIG_DFL);
      signal (SIGTTIN, SIG_DFL);
      signal (SIGTTOU, SIG_DFL);
      signal (SIGCHLD, SIG_DFL);
    }

  /* Standart girdi/çıktı kanallarını yeni sürece ayarlayalım.  */
  if (infile != STDIN_FILENO)
    {
      dup2 (infile, STDIN_FILENO);
      close (infile);
    }
  if (outfile != STDOUT_FILENO)
    {
      dup2 (outfile, STDOUT_FILENO);
      close (outfile);
    }
  if (errfile != STDERR_FILENO)
    {
      dup2 (errfile, STDERR_FILENO);
      close (errfile);
    }

  /* Yeni süreci çalıştıralım ve çıkalım.  */
  execvp (p->argv[0], p->argv);
  perror ("execvp");
  exit (1);
}
Kabuk etkileşimli olarak çalışmıyorsa, bu işlev süreç grubu ve sinyallerle ilgili olarak hiçbir şey yapmaz. İş denetimi yapmayan bir kabuğun kendi alt süreçlerini kendi süreç grubunda tuttuğunu hatırlayın.
Aşağıda, bir işi tam anlamıyla çalıştıran bir işleve yer verilmiştir. Alt süreç oluşturulduktan sonra, bu işlev yeni oluşturulan işi önalana ya da artalana koyacak bazı işlevleri çağırır; bunlar Önalan ve Artalan bölümünde açıklanmıştır.
void
launch_job (job *j, int foreground)
{
  process *p;
  pid_t pid;
  int mypipe[2], infile, outfile;

  infile = j->stdin;
  for (p = j->first_process; p; p = p->next)
    {
      /* Set up pipes, if necessary.  */
      if (p->next)
        {
          if (pipe (mypipe) < 0)
            {
              perror ("pipe");
              exit (1);
            }
          outfile = mypipe[1];
        }
      else
        outfile = j->stdout;

      /* Alt süreci çatallayalım.  */
      pid = fork ();
      if (pid == 0)
        /* This is the child process.  */
        launch_process (p, j->pgid, infile,
                        outfile, j->stderr, foreground);
      else if (pid < 0)
        {
          /* Çatallama başarısız.  */
          perror ("fork");
          exit (1);
        }
      else
        {
          /* Bu, ata süreç.  */
          p->pid = pid;
          if (shell_is_interactive)
            {
              if (!j->pgid)
                j->pgid = pid;
              setpgid (pid, j->pgid);
            }
        }

      /* Boruları temizleyelim.  */
      if (infile != j->stdin)
        close (infile);
      if (outfile != j->stdout)
        close (outfile);
      infile = mypipe[0];
    }

  format_job_info (j, "işe başladı");

  if (!shell_is_interactive)
    wait_for_job (j);
  else if (foreground)
    put_job_in_foreground (j, 0);
  else
    put_job_in_background (j, 0);
}
Önceki Üst Ana Başlık Sonraki
Kabuğun İlklendirilmesi Başlangıç Önalan ve Artalan
Bir Linux Kitaplığı Sayfası