English static mirror for SEO/GEO · AI-assisted translation · Read Chinese original

PTTBBS Deep Dive: Architecture and Multi-User Design of Taiwan's Largest BBS

Forum topic · 小凯 · 2026-04-07

Summary

PTTBBS is the open-source software behind PTT.cc, Taiwan's largest Bulletin Board System, developed by National Taiwan University students and running since 1995. It serves over 300,000 registered users across thousands of boards, supporting Telnet, SSH, and WebSocket access. The system uses a one-process-per-connection model, where each mbbsd child process handles a single user and communicates through SysV shared memory (Key 1228, ~4MB) containing user hashes, online user tables (utmp), and board caches. Storage relies entirely on the filesystem: fixed-length records in .PASSWDS for users, .BRD for boards, and per-board .DIR index files containing 128-byte fileheader_t records alongside individual article files named M.timestamp.category.sequence. Concurrency is managed via POSIX file locking on record offsets, System V semaphores, and atomic temp-file-plus-rename updates. Modern deployments add Nginx with wsproxy for browser access, or HAProxy-fronted clusters with NFS for distributed file storage. The design embodies Unix philosophy: no database, no threads, packed structs for O(1) access, and backward compatibility preserved for three decades.

Key Points

Overview

  • PTTBBS powers PTT.cc, Taiwan's largest BBS, running continuously since 1995
  • Built and maintained by National Taiwan University students
  • Serves 300,000+ registered users across thousands of boards (subforums)
  • Text-only system based on Telnet, with SSH and WebSocket gateways
  • Architecture

  • Process model: one mbbsd child process per connection (forked from parent daemon)
  • Client access layer: Telnet (port 23), SSH (port 22), WebSocket (via wsproxy)
  • Shared memory: SysV IPC, key 1228, ~4MB, contains three structures:
  • uhash: user-ID hash table (userid → uid mapping)
  • utmp: online user table (userinfo_t[])
  • bcache: board header cache (boardheader_t[])
  • Filesystem storage: all persistent data lives in flat files under BBSHOME
  • Core Data Structures

  • userec_t (~400 bytes): fixed-length user record in .PASSWDS, fields include userid, encrypted password, userlevel, login days, post count, money (P-coins), email, career
  • boardheader_t (256 bytes): board name, Chinese title, BM list, attribute flags, parent/child pointers, access level
  • fileheader_t (128 bytes): post index entry stored in .DIR files, contains filename, modify time, recommendation count, author, date, title, multi-purpose union (money/anon_uid/vote/refer)
  • All structs use __attribute__((packed)) for fixed size and O(1) random access
  • Multi-User Mechanics

  • Inter-user messaging: queued in msgs[] array of userinfo_t; receiver process gets SIGUSR1
  • Real-time chat: destuid field points to partner's userinfo_t, paired with signal notification
  • Friend presence: friend_online[] bit/flag array maps directly into utmp indexes
  • Post filenames: M.<Unix-timestamp>.<A-Z>.<hex-sequence>
  • .DIR format: flat array of 128-byte fileheader_t records, oldest to newest
  • Concurrency Control

  • File locking: filelocking(fd, F_WRLCK, uid * sizeof(userec_t), sizeof(userec_t)) for record-level locking on .PASSWDS
  • Semaphores: SysV semget/semop for protecting SHM counters (e.g., PASSWDSEM_KEY=2010)
  • Atomic updates: write to .DIR.tmp, then rename() for crash-safe replacement
  • Deployment Patterns

    1. Single host (traditional): supports ~1000–2000 concurrent connections, limited by process count and memory 2. WebSocket gateway: Browser → Nginx (TLS termination) → wsproxy → mbbsd on localhost:23, no mbbsd modification required 3. Distributed (large site): HAProxy fronting multiple mbbsd instances behind shared NFS storage; SHM cannot cross machines, so Redis/Memcached or DPDK/RDMA is needed to replace local shared memory

    Performance Techniques

  • Packed structs prevent compiler padding
  • FNV-1a hash with 1 << HASH_BITS (≈65,536) buckets, average chain length 2–3 for MAX_USERS=150,000
  • Per-board .DIR mmap'd into headers[] array on board entry
  • Design Philosophy

  • No database, only files; no threads, only processes
  • Fixed-length records + hash table ≈ efficient key-value store
  • Shared memory holds all hot state (user presence, online list, board cache)
  • Unix-philosophy separation: mbbsd handles connections, daemon/ runs background tasks
  • Backward compatibility preserved since 1995
  • Comparison With Modern Stacks

    | Aspect | PTTBBS (1995) | Modern Forum (2024) | |---|---|---| | Protocol | Telnet (text) | HTTP / WebSocket | | Architecture | Process per connection | Thread pool / async I/O | | Storage | Binary flat files | RDBMS | | Cache | SysV shared memory | Redis / Memcached | | Deployment | Single host | Microservices / containers | | Frontend | Terminal emulator | React / Vue | | Password hashing | DES | bcrypt / Argon2 |

    Bottom Line

    PTTBBS demonstrates that text-only interfaces can sustain million-user communities, that flat-file storage with fixed-length records can replace a database for the right access pattern, and that SysV shared memory is an effective IPC mechanism for multi-process servers. Constrained by 1995-era hardware (32MB RAM, single-core CPU, dial-up), the codebase remains an instructive case study in resource-efficient systems design.

    References

  • Source: https://github.com/ptt/pttbbs
  • Site: https://www.ptt.cc
  • Wikipedia: https://zh.wikipedia.org/wiki/批踢踢

Tags

#pttbbs#bbs#architecture#multi-user#shared-memory#sysv-ipc#telnet#websocket

This page is an English static mirror generated for search and AI citation. It may be a full translation or structured summary of the Chinese original. Canonical interactive discussion lives on the Chinese page: https://zhichai.net/topic/177169640