---
title: 'The Package Manager Concept'
source: 'https://academia.sh/en/courses/introduction-to-linux/package-manager-concept'
course: 'Introduction to Linux'
language: en
updated: '2026-08-17T18:09:56+00:00'
license: 'CC BY-SA 4.0'
---

# The Package Manager Concept

A package's structure as files plus metadata, the function of the installed-package database, dependency resolution as a constraint problem, and version comparison rules.

Every tool used throughout the course was already present on the system. How it got there,
how it is updated, and how it is removed was never asked.

The question is harder than it looks. Installing a program is not just copying files: the
executable goes into one directory, its libraries into another, its configuration under
`/etc`, its documentation into the manual directory — exactly the distribution the layout
standard from the directory hierarchy lesson defined. Done by hand, no record exists of which
file belongs to which program, and removal becomes impossible.

## What a Package Is

A **package** is an archive carrying the files to be installed together with metadata about
those files. Its structure resembles the format from the archiving lesson: a file tree plus
header information. The difference is that the header is read for installation decisions.

The information metadata carries shows naming differences across package manager families, but
the fields are common:

| Field | Function |
|---|---|
| Name | The package's identity |
| Version | Which release it is |
| Architecture | Which processor family it was built for |
| Dependencies | Other packages required for it to run |
| Conflicts | Packages it cannot be installed alongside |
| Provides | The abstract capability names it satisfies |
| Checksums | A content digest of every file |
| Install scripts | Steps to run before and after installation |

The last two fields are often skipped over but are decisive. Checksums make it possible to test
whether installed files have since been modified — the system-scale counterpart of the
verification method from the file transfer lesson. Install scripts cover the cases file
copying alone cannot: opening a user account, registering a service, adjusting a database —
and because they run with root privilege, they sit at the center of package trust.

## The Installed-Package Database

A package manager's second component is a local database holding a record of every package
installed on the system. The record contains the package's metadata and the full list of
files it installed.

Without this list, three operations cannot be done.

**Removal.** Which files to delete cannot be known; software installed by hand leaves remnants
behind when removed.

**Upgrading.** Which files of the old version are absent from the new one cannot be known;
remnant files accumulate.

**Ownership query.** Which package a file on the system belongs to cannot be asked; this query
is used to determine which package's responsibility a fault should be charged to.

Another consequence of the database is that **manually modified files** can be distinguished.
Configuration files ship with the package but are edited by the administrator; on upgrade,
these changes need to be preserved. Package managers compare a file's checksum against the
recorded one to tell whether it has changed, and if it has, they ask the user instead of
overwriting it on upgrade.

## Why Dependencies Exist

A dependency is not an abstract concept; it can be seen in the executables themselves:

```
$ ldd /usr/bin/ls
	linux-vdso.so.1 (0x0000ffff88cce000)
	libselinux.so.1 => /lib/aarch64-linux-gnu/libselinux.so.1 (0x0000ffff88be0000)
	libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffff88a20000)
	/lib/ld-linux-aarch64.so.1 (0x0000ffff88c80000)
	libpcre2-8.so.0 => /lib/aarch64-linux-gnu/libpcre2-8.so.0 (0x0000ffff88970000)
```

The listing command does not run on its own: it depends on the standard C library, the
security-labeling library, and the regular expression library. The numbers in parentheses are
the libraries' load addresses for that particular run and change on every invocation; the
library names do not change. These libraries come in separate packages. The linking and
loading lesson in the How Computers Work course defined this relationship; package
dependencies are that relationship's distribution-level counterpart.

The reason for using a shared library is avoiding duplication: hundreds of programs do not
each carry a separate copy of the same library. The cost is that installation turns into a
dependency graph.

The **provides** concept loosens this graph. A package can supply an abstract capability name alongside its
concrete one; other packages depend not on the concrete name but on the capability, so
different implementations doing the same job can substitute for one another. This is the
packaging-level counterpart of the `/bin/sh` example from the shell lesson: a dependency is
built on a role, and which program fills that role is the system's decision.

## Resolution Is a Constraint Problem

When a package's installation is requested, the question that must be solved is: which
packages, added to the currently installed set, satisfy every dependency and produce no
conflict?

This is a search problem. A small example shows its shape:

| Package | Dependency | Conflict |
|---|---|---|
| `plot` 2.0 | `graphics` ≥ 3 | — |
| `report` 1.4 | `graphics` ≤ 2 | — |
| `graphics` 2.9 | — | — |
| `graphics` 3.1 | — | — |

`plot` and `report` cannot be installed on the same system: one wants the third release of
the `graphics` library, the other wants at most the second. The resolver reports this and
waits for the user to choose. On real systems this graph carries tens of thousands of nodes,
and constraints grow complex with intersections, alternatives, and version ranges.

Resolution ends in one of three states: a solution is found and a list of actions is
presented; no solution exists and a conflict is reported; or multiple solutions exist and the
manager's preference rules — which repository takes priority, which version is preferred —
take over.

For this reason, installation commands **list what they will do and ask for confirmation**
before acting. The list carries not just the requested package but every dependency it pulls
in and everything that needs removing; it should not be approved without being read.

## Version Comparison

Since dependencies set constraints of the form "at least this version," versions must be
comparable. Comparison cannot be done lexicographically:

- Version `1.10` is **greater than** `1.9`, but compared as text it looks smaller.
- `2.0` and `2.0.0` are treated as equal under most rules.
- Version `1.0-beta` is **less than** `1.0`; letter-bearing suffixes signal pre-release.

For this reason every package manager family has a defined comparison algorithm: the version
string is split into numeric and alphabetic parts, numeric parts are compared as numbers,
alphabetic parts are compared in order.

There is also a need to override ordering by hand. When a piece of software's version
numbering scheme changes, the new version can look smaller than the old one. To handle this, a
number consulted before anything else during comparison is prepended to the version string;
when this number increases, every subsequent comparison favors the new scheme.

## Package Manager Classes

Tools operate at two levels, and the split exists in every family.

The **low-level tool** deals with a single package file: it unpacks it, places the files,
records it in the database. It does **not** resolve dependencies; it errors out if one is
missing. Querying installed packages is also at this level.

The **high-level tool** knows about repositories, resolves dependencies, downloads, and calls
the low-level tool. This is the tool a user works with day to day.

The split has a practical consequence: if a package file is in hand and installed with the
low-level tool, dependencies can be left unsatisfied. The correct approach is handing the file
to the high-level tool, so missing dependencies are filled in from the repository.

There is also a domain outside the system package manager: programming languages' own package
managers. The two keep separate databases and are unaware of each other. If the same library
is installed through both, which copy gets used becomes ambiguous. Common practice is
installing language-level packages not into system directories but into a project- or
user-specific area.

## Summary

- A package is an archive carrying the files to install and metadata; the metadata includes
  dependency, conflict, checksum, and install-script information.
- The installed-package database is the record that makes removal, upgrading, and file
  ownership queries possible.
- Dependencies are the concrete result of shared libraries; abstract capability names let
  different implementations substitute for one another.
- Installation is a constraint problem; a solution may not exist or may not be unique, so
  tools present the action list for approval.
- Version comparison cannot be done lexicographically; a version string is split into numeric
  and alphabetic parts for comparison.
- The low-level tool deals with a single package and does not resolve dependencies; the
  high-level tool knows about repositories and performs resolution.

## Next Step

With the concepts established, operations can be covered. The next lesson introduces the set
of operations every package manager has a counterpart for, whatever its family: updating the
index, installing, removing, purging along with configuration, querying, and verifying — and
which of these operations can be undone.
