mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 20:17:44 +00:00
Add a PTY multiplexer (/dev/ptmx) device.
When you open /dev/ptmx, you get a file descriptor pointing to one of the available MasterPTY's. If none are available, you get an EBUSY. This makes it possible to open multiple (up to 4) Terminals. :^) To support this, I also added a CharacterDevice::open() that gets control when VFS is opening a CharacterDevice. This is useful when we want to return a custom FileDescriptor like we do here.
This commit is contained in:
parent
b46ae2bf09
commit
9dd29f9aa9
13 changed files with 75 additions and 37 deletions
|
@ -19,6 +19,7 @@ KERNEL_OBJS = \
|
|||
ProcFileSystem.o \
|
||||
RTC.o \
|
||||
TTY.o \
|
||||
PTYMultiplexer.o \
|
||||
MasterPTY.o \
|
||||
SlavePTY.o \
|
||||
VirtualConsole.o \
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
class SlavePTY;
|
||||
|
||||
class MasterPTY final : public CharacterDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
explicit MasterPTY(unsigned index);
|
||||
virtual ~MasterPTY() override;
|
||||
|
@ -17,6 +16,7 @@ public:
|
|||
virtual bool can_write(Process&) const override;
|
||||
virtual bool is_master_pty() const override { return true; }
|
||||
|
||||
unsigned index() const { return m_index; }
|
||||
String pts_name() const;
|
||||
void on_slave_write(const byte*, size_t);
|
||||
|
||||
|
|
27
Kernel/PTYMultiplexer.cpp
Normal file
27
Kernel/PTYMultiplexer.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include "PTYMultiplexer.h"
|
||||
#include "MasterPTY.h"
|
||||
#include <LibC/errno_numbers.h>
|
||||
|
||||
PTYMultiplexer::PTYMultiplexer()
|
||||
: CharacterDevice(5, 2)
|
||||
{
|
||||
m_freelist.ensureCapacity(4);
|
||||
for (int i = 4; i > 0; --i)
|
||||
m_freelist.unchecked_append(adopt(*new MasterPTY(i - 1)));
|
||||
}
|
||||
|
||||
PTYMultiplexer::~PTYMultiplexer()
|
||||
{
|
||||
}
|
||||
|
||||
RetainPtr<FileDescriptor> PTYMultiplexer::open(int& error, int options)
|
||||
{
|
||||
LOCKER(m_lock);
|
||||
if (m_freelist.is_empty()) {
|
||||
error = -EBUSY;
|
||||
return nullptr;
|
||||
}
|
||||
auto master = m_freelist.takeLast();
|
||||
dbgprintf("PTYMultiplexer::open: Vending master %u\n", master->index());
|
||||
return VFS::the().open(move(master), error, options);
|
||||
}
|
24
Kernel/PTYMultiplexer.h
Normal file
24
Kernel/PTYMultiplexer.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include <VirtualFileSystem/CharacterDevice.h>
|
||||
#include <AK/Lock.h>
|
||||
|
||||
class MasterPTY;
|
||||
|
||||
class PTYMultiplexer final : public CharacterDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
PTYMultiplexer();
|
||||
virtual ~PTYMultiplexer() override;
|
||||
|
||||
// ^CharacterDevice
|
||||
virtual RetainPtr<FileDescriptor> open(int& error, int options) override;
|
||||
virtual ssize_t read(Process&, byte*, size_t) override { return 0; }
|
||||
virtual ssize_t write(Process&, const byte*, size_t) override { return 0; }
|
||||
virtual bool can_read(Process&) const override { return true; }
|
||||
virtual bool can_write(Process&) const override { return true; }
|
||||
|
||||
private:
|
||||
SpinLock m_lock;
|
||||
Vector<RetainPtr<MasterPTY>> m_freelist;
|
||||
};
|
|
@ -617,9 +617,10 @@ Process::Process(String&& name, uid_t uid, gid_t gid, pid_t ppid, RingLevel ring
|
|||
} else {
|
||||
m_fds.resize(m_max_open_file_descriptors);
|
||||
if (tty) {
|
||||
m_fds[0].set(tty->open(O_RDONLY));
|
||||
m_fds[1].set(tty->open(O_WRONLY));
|
||||
m_fds[2].set(tty->open(O_WRONLY));
|
||||
int error;
|
||||
m_fds[0].set(tty->open(error, O_RDONLY));
|
||||
m_fds[1].set(tty->open(error, O_WRONLY));
|
||||
m_fds[2].set(tty->open(error, O_WRONLY));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
class MasterPTY;
|
||||
|
||||
class SlavePTY final : public TTY {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
virtual ~SlavePTY() override;
|
||||
|
||||
virtual String tty_name() const override;
|
||||
|
||||
void on_master_write(const byte*, size_t);
|
||||
unsigned index() const { return m_index; }
|
||||
|
||||
protected:
|
||||
virtual void on_tty_write(const byte*, size_t) override;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "VirtualConsole.h"
|
||||
#include "Scheduler.h"
|
||||
#include "PS2MouseDevice.h"
|
||||
#include "MasterPTY.h"
|
||||
#include "PTYMultiplexer.h"
|
||||
|
||||
#define SPAWN_GUI_TEST_APP
|
||||
//#define SPAWN_MULTIPLE_SHELLS
|
||||
|
@ -37,10 +37,6 @@ VirtualConsole* tty3;
|
|||
Keyboard* keyboard;
|
||||
PS2MouseDevice* ps2mouse;
|
||||
GUIEventDevice* gui_event_device;
|
||||
MasterPTY* ptm0;
|
||||
MasterPTY* ptm1;
|
||||
MasterPTY* ptm2;
|
||||
MasterPTY* ptm3;
|
||||
|
||||
#ifdef STRESS_TEST_SPAWNING
|
||||
static void spawn_stress() NORETURN;
|
||||
|
@ -80,10 +76,8 @@ static void init_stage2()
|
|||
auto dev_random = make<RandomDevice>();
|
||||
vfs->register_character_device(*dev_random);
|
||||
|
||||
VFS::the().register_character_device(*new MasterPTY(0));
|
||||
VFS::the().register_character_device(*new MasterPTY(1));
|
||||
VFS::the().register_character_device(*new MasterPTY(2));
|
||||
VFS::the().register_character_device(*new MasterPTY(3));
|
||||
auto dev_ptmx = make<PTYMultiplexer>();
|
||||
vfs->register_character_device(*dev_ptmx);
|
||||
|
||||
vfs->register_character_device(*keyboard);
|
||||
vfs->register_character_device(*ps2mouse);
|
||||
|
|
|
@ -9,6 +9,7 @@ mknod mnt/dev/tty1 c 4 1
|
|||
mknod mnt/dev/tty2 c 4 2
|
||||
mknod mnt/dev/tty3 c 4 3
|
||||
mknod mnt/dev/psaux c 10 1
|
||||
mknod mnt/dev/ptmx c 5 2
|
||||
mknod mnt/dev/ptm0 c 10 0
|
||||
mknod mnt/dev/ptm1 c 10 1
|
||||
mknod mnt/dev/ptm2 c 10 2
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue