Advanced Programming in UNIX Environment Episode 35

Process Relationship

Introduction

In this chapter, we’ll look at process groups in more detail and the concept of sessions that was introduced by POSIX.1. We’ll also look at the relationship between the login shell that is invoked for us when we log in and all the processes that we start from our login shell.

Terminal Logins

Let’s start by looking at the programs that are executed when we log in to a UNIX system. In early UNIX systems, such as Version 7, users logged in using dumb terminals that were connected to the host with hard-wired connections. The terminals were either local (directly connected) or remote (connected through a modem).

Today, some platforms allow you to start a windowing system after logging in, whereas other platforms automatically start the windowing system for you. In the latter case, you might still have to log in, depending on how the windowing system is configured (some windowing systems can be configured to log you in automatically).

The BSD terminal login procedure has not changed much over the past 35 years. The system administrator creates a file, usually /etc/ttys, that has one line per terminal device. Each line specifies the name of the device and other parameters that are passed to the getty program. One parameter is the baud rate of the terminal, for example. When the system is bootstrapped, the kernel creates process ID 1, the init process, and it is init that brings the system up in multiuser mode. The init process reads the file /etc/ttys and, for every terminal device that allows a login, does a fork followed by an exec of the program getty.

When we enter our user name, getty’s job is complete, and it then invokes the login program, similar to

execle("/bin/login", "login", "-p", username, (char *)0, envp);

(There can be options in the gettytab file to have it invoke other programs, but the
default is the login program.)

Since it has our user name, it can call getpwnam to fetch our password file entry. Then login calls getpass(3) to display the prompt Password: and read our password (with echoing disabled, of course). It calls crypt(3) to encrypt the password that we entered and compares the encrypted result to the pw_passwd field from our shadow password file entry. If the login attempt fails because of an invalid password (after a few tries), login calls exit with an argument of 1. This termination will be noticed by the parent (init), and it will do another fork followed by an exec of getty, starting the procedure over again for this terminal.

This is the traditional authentication procedure used on UNIX systems. Modern
UNIX systems, however, have evolved to support multiple authentication procedures. For example, FreeBSD, Linux, Mac OS X, and Solaris all support a more flexible scheme known as PAM (Pluggable Authentication Modules). PAM allows an administrator to configure the authentication methods to be used to access services that are written to use the PAM library.

If we log in correctly, login will

  • Change to our home directory (chdir)
  • Change the ownership of our terminal device (chown) so we own it
  • Change the access permissions for our terminal device so we have permission to
    read from and write to it
  • Set our group IDs by calling setgid and initgroups
  • Initialize the environment with all the information that login has: our home
    directory (HOME), shell (SHELL), user name (USER and LOGNAME), and a default
    path (PATH)
  • Change to our user ID (setuid) and invoke our login shell, as in
execl("/bin/sh", "-sh", (char *)0);

The minus sign as the first character of argv[0] is a flag to all the shells that indicates they are being invoked as a login shell. The shells can look at this character and modify their start-up accordingly.

The login program really does more than we’ve described here.

Our login shell now reads its start-up files (.profile for the Bourne shell and Korn shell; .bash_profile, .bash_login, or .profile for the GNU Bourne-again shell; and .cshrc and .login for the C shell).

On Mac OS X, the terminal login process follows essentially the same steps as in the BSD login process, since Mac OS X is based in part on FreeBSD. With Mac OS X, however, there are some differences:

  • The work of init is performed by launchd.
  • We are presented with a graphical-based login screen from the start.

Some Linux distributions ship with a version of the init program that uses administrative files patterned after System V/etc/inittab contains the configuration information specifying the terminal devices for which init should start a getty process.

Other Linux distributions, such as recent Ubuntu distributions, ship with a version of init that is known as ‘‘Upstart.’’ It uses configuration files named *.conf that are stored in the /etc/init directory.

Solaris supports two forms of terminal logins: (a) getty style, as described previously for BSD, and (b) ttymon logins, a feature introduced with SVR4. Normally, getty is used for the console, and ttymon is used for other terminal logins.

The ttymon command is part of a larger facility termed SAF, the Service Access Facility. The goal of the SAF was to provide a consistent way to administer services that provide access to a system.

Network Logins

The main (physical) difference between logging in to a system through a serial terminal and logging in to a system through a network is that the connection between the terminal and the computer isn’t point-to-point. In this case, login is simply a service available, just like any other network service, such as FTP or SMTP.

To allow the same software to process logins over both terminal logins and network logins, a software driver called a pseudo terminal is used to emulate the behavior of a serial terminal and map terminal operations to network operations, and vice versa.

In BSD, a single process waits for most network connections: the inetd process, sometimes called the Internet superserver. In this section, we’ll look at the sequence of processes involved in network logins for a BSD system.

Let’s assume that a TCP connection request arrives for the TELNET server. TELNET is a remote login application that uses the TCP protocol. A user on another host (that is connected to the server’s host through a network of some form) or on the same host initiates the login by starting the TELNET client:

telnet hostname

The client opens a TCP connection to hostname, and the program that’s started on hostname is called the TELNET server. The client and the server then exchange data across the TCP connection using the TELNET application protocol. What has happened is that the user who started the client program is now logged in to the server’s host.

The telnetd process then opens a pseudo terminal device and splits into two processes using fork. The parent handles the communication across the network connection, and the child does an exec of the login program. The parent and the child are connected through the pseudo terminal. Before doing the exec, the child sets up file descriptors 0, 1, and 2 to the pseudo terminal.

Obviously, a lot is going on between the pseudo terminal device driver and the actual user at the terminal.

Logging in to a Mac OS X system over a network is identical to logging in to a BSD system, because Mac OS X is based partially on FreeBSD. However, on Mac OS X, the telnet daemon is run from launchd.

By default, the telnet daemon is disabled on Mac OS X (although it can be enabled with the launchctl(1) command). The preferred way to perform a network login on Mac OS X is with ssh, the secure shell command.

Network logins under Linux are the same as under BSD, except that some distributions use an alternative inetd process called the extended Internet services daemon, xinetd. The xinetd process provides a finer level of control over services it starts compared to inetd.

The scenario for network logins under Solaris is almost identical to the steps under BSD and Linux. An inetd server is used that is similar in concept to the BSD version, except that the Solaris version runs as a restarter in the Service Management Facility (SMF). A restarter is a daemon that has the responsibility to start and monitor other daemon processes, and restart them if they fail. Although the inetd server is started by the master restarter in the SMF, the master restarter is started by init.

The Solaris Service Management Facility is a framework that manages and monitors system services and provides a way to recover from failures affecting system services.

Process Groups

A process group is a collection of one or more processes, usually associated with the same job (job control is discussed in Section 9.8), that can receive signals from the same terminal. Each process group has a unique process group ID. Process group IDs are similar to process IDs: they are positive integers and can be stored in a pid_t data type. The function getpgrp returns the process group ID of the calling process.

#include <unistd.h>
pid_t getpgrp(void);

In older BSD-derived systems, the getpgrp function took a pid argument and returned the process group for that process. The Single UNIX Specification defines the getpgid function that mimics this behavior.

#include <unistd.h>
pid_t getpgid(pid_t pid);

If pid is 0, the process group ID of the calling process is returned. Thus

getpgid(0);

is equivalent to

getpgrp();

Each process group can have a process group leader. The leader is identified by its process group ID being equal to its process ID.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值