linux源代码剖析之include-linux

include-linux
config.h
#ifndef _CONFIG_H
#define _CONFIG_H

/* #define LASU_HD */
#define LINUS_HD

/*

  • Amount of ram memory (in bytes, 640k-1M not discounted). Currently 8Mb.
  • Don’t make this bigger without making sure that there are enough page
  • directory entries (boot/head.s)
    */
    #if defined(LINUS_HD)
    #define HIGH_MEMORY (0x800000)
    #elif defined(LASU_HD)
    #define HIGH_MEMORY (0x400000)
    #else
    #error “must define hd”
    #endif

/* End of buffer memory. Must be 0xA0000, or > 0x100000, 4096-byte aligned */
#if (HIGH_MEMORY>=0x600000)
#define BUFFER_END 0x200000
#else
#define BUFFER_END 0xA0000
#endif

/* Root device at bootup. */
#if defined(LINUS_HD)
#define ROOT_DEV 0x306
#elif defined(LASU_HD)
#define ROOT_DEV 0x302
#else
#error “must define HD”
#endif

/*

  • HD type. If 2, put 2 structures with a comma. If just 1, put
  • only 1 struct. The structs are { HEAD, SECTOR, TRACKS, WPCOM, LZONE, CTL }
  • NOTE. CTL is supposed to be 0 for drives with less than 8 heads, and
  • 8 if heads >= 8. Don’t know why, and I haven’t tested it on a drive with
  • more than 8 heads, but that is what the bios-listings seem to imply. I
  • just love not having a manual.
    */
    #if defined(LASU_HD)
    #define HD_TYPE { 7,35,915,65536,920,0 }
    #elif defined(LINUS_HD)
    #define HD_TYPE { 5,17,980,300,980,0 },{ 5,17,980,300,980,0 }
    #else
    #error “must define a hard-disk type”
    #endif

#endif



fs.h
/*

  • This file has definitions for some important file table
  • structures etc.
    */

#ifndef _FS_H
#define _FS_H

#include <sys/types.h>

/* devices are as follows: (same as minix, so we can use the minix

  • file system. These are major numbers.)
  • 0 - unused (nodev)
  • 1 - /dev/mem
  • 2 - /dev/fd
  • 3 - /dev/hd
  • 4 - /dev/ttyx
  • 5 - /dev/tty
  • 6 - /dev/lp
  • 7 - unnamed pipes
    */

#define IS_BLOCKDEV(x) ((x)==2 || (x)==3)

#define READ 0
#define WRITE 1

void buffer_init(void);

#define MAJOR(a) (((unsigned)(a))>>8)
#define MINOR(a) ((a)&0xff)

#define NAME_LEN 14

#define I_MAP_SLOTS 8
#define Z_MAP_SLOTS 8
#define SUPER_MAGIC 0x137F

#define NR_OPEN 20
#define NR_INODE 32
#define NR_FILE 64
#define NR_SUPER 8
#define NR_HASH 307
#define NR_BUFFERS nr_buffers
#define BLOCK_SIZE 1024
#ifndef NULL
#define NULL ((void *) 0)
#endif

#define INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct d_inode)))
#define DIR_ENTRIES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct dir_entry)))

typedef char buffer_block[BLOCK_SIZE];

struct buffer_head {
char * b_data; /* pointer to data block (1024 bytes) /
unsigned short b_dev; /
device (0 = free) /
unsigned short b_blocknr; /
block number /
unsigned char b_uptodate;
unsigned char b_dirt; /
0-clean,1-dirty /
unsigned char b_count; /
users using this block /
unsigned char b_lock; /
0 - ok, 1 -locked */
struct task_struct * b_wait;
struct buffer_head * b_prev;
struct buffer_head * b_next;
struct buffer_head * b_prev_free;
struct buffer_head * b_next_free;
};

struct d_inode {
unsigned short i_mode;
unsigned short i_uid;
unsigned long i_size;
unsigned long i_time;
unsigned char i_gid;
unsigned char i_nlinks;
unsigned short i_zone[9];
};

struct m_inode {
unsigned short i_mode;
unsigned short i_uid;
unsigned long i_size;
unsigned long i_mtime;
unsigned char i_gid;
unsigned char i_nlinks;
unsigned short i_zone[9];
/* these are in memory also */
struct task_struct * i_wait;
unsigned long i_atime;
unsigned long i_ctime;
unsigned short i_dev;
unsigned short i_num;
unsigned short i_count;
unsigned char i_lock;
unsigned char i_dirt;
unsigned char i_pipe;
unsigned char i_mount;
unsigned char i_seek;
unsigned char i_update;
};

#define PIPE_HEAD(inode) (((long *)((inode).i_zone))[0])
#define PIPE_TAIL(inode) (((long *)((inode).i_zone))[1])
#define PIPE_SIZE(inode) ((PIPE_HEAD(inode)-PIPE_TAIL(inode))&(PAGE_SIZE-1))
#define PIPE_EMPTY(inode) (PIPE_HEAD(inode)PIPE_TAIL(inode))
#define PIPE_FULL(inode) (PIPE_SIZE(inode)
(PAGE_SIZE-1))
#define INC_PIPE(head)
asm(“incl %0\n\tandl $4095,%0”::“m” (head))

struct file {
unsigned short f_mode;
unsigned short f_flags;
unsigned short f_count;
struct m_inode * f_inode;
off_t f_pos;
};

struct super_block {
unsigned short s_ninodes;
unsigned short s_nzones;
unsigned short s_imap_blocks;
unsigned short s_zmap_blocks;
unsigned short s_firstdatazone;
unsigned short s_log_zone_size;
unsigned long s_max_size;
unsigned short s_magic;
/* These are only in memory */
struct buffer_head * s_imap[8];
struct buffer_head * s_zmap[8];
unsigned short s_dev;
struct m_inode * s_isup;
struct m_inode * s_imount;
unsigned long s_time;
unsigned char s_rd_only;
unsigned char s_dirt;
};

struct dir_entry {
unsigned short inode;
char name[NAME_LEN];
};

extern struct m_inode inode_table[NR_INODE];
extern struct file file_table[NR_FILE];
extern struct super_block super_block[NR_SUPER];
extern struct buffer_head * start_buffer;
extern int nr_buffers;

extern void truncate(struct m_inode * inode);
extern void sync_inodes(void);
extern void wait_on(struct m_inode * inode);
extern int bmap(struct m_inode * inode,int block);
extern int create_block(struct m_inode * inode,int block);
extern struct m_inode * namei(const char * pathname);
extern int open_namei(const char * pathname, int flag, int mode,
struct m_inode ** res_inode);
extern void iput(struct m_inode * inode);
extern struct m_inode * iget(int dev,int nr);
extern struct m_inode * get_empty_inode(void);
extern struct m_inode * get_pipe_inode(void);
extern struct buffer_head * get_hash_table(int dev, int block);
extern struct buffer_head * getblk(int dev, int block);
extern void ll_rw_block(int rw, struct buffer_head * bh);
extern void brelse(struct buffer_head * buf);
extern struct buffer_head * bread(int dev,int block);
extern int new_block(int dev);
extern void free_block(int dev, int block);
extern struct m_inode * new_inode(int dev);
extern void free_inode(struct m_inode * inode);

extern void mount_root(void);

extern inline struct super_block * get_super(int dev)
{
struct super_block * s;

for(s = 0+super_block;s < NR_SUPER+super_block; s++)
	if (s->s_dev == dev)
		return s;
return NULL;

}

#endif



hdreg.h
/*

  • This file contains some defines for the AT-hd-controller.
  • Various sources. Check out some definitions (see comments with
  • a ques).
    */
    #ifndef _HDREG_H
    #define _HDREG_H

/* currently supports only 1 hd, put type here */
#define HARD_DISK_TYPE 17

/*

  • Ok, hard-disk-type is currently hardcoded. Not beatiful,
  • but easier. We don’t use BIOS for anything else, why should
  • we get HD-type from it? Get these values from Reference Guide.
    */

#if HARD_DISK_TYPE == 17
#define _CYL 977
#define _HEAD 5
#define __WPCOM 300
#define _LZONE 977
#define _SECT 17
#define _CTL 0
#elif HARD_DISK_TYPE == 18
#define _CYL 977
#define _HEAD 7
#define __WPCOM (-1)
#define _LZONE 977
#define _SECT 17
#define _CTL 0
#else
#error Define HARD_DISK_TYPE and parameters, add your own entries as well
#endif

/* Controller wants just wp-com/4 */
#if __WPCOM >= 0
#define _WPCOM ((__WPCOM)>>2)
#else
#define _WPCOM __WPCOM
#endif

/* Hd controller regs. Ref: IBM AT Bios-listing /
#define HD_DATA 0x1f0 /
_CTL when writing /
#define HD_ERROR 0x1f1 /
see err-bits /
#define HD_NSECTOR 0x1f2 /
nr of sectors to read/write /
#define HD_SECTOR 0x1f3 /
starting sector /
#define HD_LCYL 0x1f4 /
starting cylinder /
#define HD_HCYL 0x1f5 /
high byte of starting cyl /
#define HD_CURRENT 0x1f6 /
101dhhhh , d=drive, hhhh=head /
#define HD_STATUS 0x1f7 /
see status-bits /
#define HD_PRECOMP HD_ERROR /
same io address, read=error, write=precomp /
#define HD_COMMAND HD_STATUS /
same io address, read=status, write=cmd */

#define HD_CMD 0x3f6

/* Bits of HD_STATUS /
#define ERR_STAT 0x01
#define INDEX_STAT 0x02
#define ECC_STAT 0x04 /
Corrected error */
#define DRQ_STAT 0x08
#define SEEK_STAT 0x10
#define WRERR_STAT 0x20
#define READY_STAT 0x40
#define BUSY_STAT 0x80

/* Values for HD_COMMAND */
#define WIN_RESTORE 0x10
#define WIN_READ 0x20
#define WIN_WRITE 0x30
#define WIN_VERIFY 0x40
#define WIN_FORMAT 0x50
#define WIN_INIT 0x60
#define WIN_SEEK 0x70
#define WIN_DIAGNOSE 0x90
#define WIN_SPECIFY 0x91

/* Bits for HD_ERROR /
#define MARK_ERR 0x01 /
Bad address mark ? /
#define TRK0_ERR 0x02 /
couldn’t find track 0 /
#define ABRT_ERR 0x04 /
? /
#define ID_ERR 0x10 /
? /
#define ECC_ERR 0x40 /
? /
#define BBD_ERR 0x80 /
? */

struct partition {
unsigned char boot_ind; /* 0x80 - active (unused) /
unsigned char head; /
? /
unsigned char sector; /
? /
unsigned char cyl; /
? /
unsigned char sys_ind; /
? /
unsigned char end_head; /
? /
unsigned char end_sector; /
? /
unsigned char end_cyl; /
? /
unsigned int start_sect; /
starting sector counting from 0 /
unsigned int nr_sects; /
nr of sectors in partition */
};

#endif



head.h
#ifndef _HEAD_H
#define _HEAD_H

typedef struct desc_struct {
unsigned long a,b;
} desc_table[256];

extern unsigned long pg_dir[1024];
extern desc_table idt,gdt;

#define GDT_NUL 0
#define GDT_CODE 1
#define GDT_DATA 2
#define GDT_TMP 3

#define LDT_NUL 0
#define LDT_CODE 1
#define LDT_DATA 2

#endif



kernel.h
/*

  • ‘kernel.h’ contains some often-used function prototypes etc
    */
    void verify_area(void * addr,int count);
    volatile void panic(const char * str);
    int printf(const char * fmt, …);
    int printk(const char * fmt, …);
    int tty_write(unsigned ch,char * buf,int count);


mm.h
#ifndef _MM_H
#define _MM_H

#define PAGE_SIZE 4096

extern unsigned long get_free_page(void);
extern unsigned long put_page(unsigned long page,unsigned long address);
extern void free_page(unsigned long addr);

#endif



sched.h
#ifndef _SCHED_H
#define _SCHED_H

#define NR_TASKS 64
#define HZ 100

#define FIRST_TASK task[0]
#define LAST_TASK task[NR_TASKS-1]

#include <linux/head.h>
#include <linux/fs.h>
#include <linux/mm.h>

#if (NR_OPEN > 32)
#error “Currently the close-on-exec-flags are in one word, max 32 files/proc”
#endif

#define TASK_RUNNING 0
#define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
#define TASK_ZOMBIE 3
#define TASK_STOPPED 4

#ifndef NULL
#define NULL ((void *) 0)
#endif

extern int copy_page_tables(unsigned long from, unsigned long to, long size);
extern int free_page_tables(unsigned long from, long size);

extern void sched_init(void);
extern void schedule(void);
extern void trap_init(void);
extern void panic(const char * str);
extern int tty_write(unsigned minor,char * buf,int count);

typedef int (*fn_ptr)();

struct i387_struct {
long cwd;
long swd;
long twd;
long fip;
long fcs;
long foo;
long fos;
long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */
};

struct tss_struct {
long back_link; /* 16 high bits zero /
long esp0;
long ss0; /
16 high bits zero /
long esp1;
long ss1; /
16 high bits zero /
long esp2;
long ss2; /
16 high bits zero /
long cr3;
long eip;
long eflags;
long eax,ecx,edx,ebx;
long esp;
long ebp;
long esi;
long edi;
long es; /
16 high bits zero /
long cs; /
16 high bits zero /
long ss; /
16 high bits zero /
long ds; /
16 high bits zero /
long fs; /
16 high bits zero /
long gs; /
16 high bits zero /
long ldt; /
16 high bits zero /
long trace_bitmap; /
bits: trace 0, bitmap 16-31 */
struct i387_struct i387;
};

struct task_struct {
/* these are hardcoded - don’t touch /
long state; /
-1 unrunnable, 0 runnable, >0 stopped /
long counter;
long priority;
long signal;
fn_ptr sig_restorer;
fn_ptr sig_fn[32];
/
various fields /
int exit_code;
unsigned long end_code,end_data,brk,start_stack;
long pid,father,pgrp,session,leader;
unsigned short uid,euid,suid;
unsigned short gid,egid,sgid;
long alarm;
long utime,stime,cutime,cstime,start_time;
unsigned short used_math;
/
file system info /
int tty; /
-1 if no tty, so it must be signed /
unsigned short umask;
struct m_inode * pwd;
struct m_inode * root;
unsigned long close_on_exec;
struct file * filp[NR_OPEN];
/
ldt for this task 0 - zero 1 - cs 2 - ds&ss /
struct desc_struct ldt[3];
/
tss for this task */
struct tss_struct tss;
};

/*

  • INIT_TASK is used to set up the first task table, touch at
  • your own risk!. Base=0, limit=0x9ffff (=640kB)
    /
    #define INIT_TASK
    /
    state etc / { 0,15,15,
    /
    signals / 0,NULL,{(fn_ptr) 0,},
    /
    ec,brk… / 0,0,0,0,0,
    /
    pid etc… / 0,-1,0,0,0,
    /
    uid etc / 0,0,0,0,0,0,
    /
    alarm / 0,0,0,0,0,0,
    /
    math / 0,
    /
    fs info / -1,0133,NULL,NULL,0,
    /
    filp / {NULL,},
    {
    {0,0},
    /
    ldt */ {0x9f,0xc0fa00},
    {0x9f,0xc0f200},
    },
    /tss/ {0,PAGE_SIZE+(long)&init_task,0x10,0,0,0,0,(long)&pg_dir,
    0,0,0,0,0,0,0,0,
    0,0,0x17,0x17,0x17,0x17,0x17,0x17,
    _LDT(0),0x80000000,
    {}
    },
    }

extern struct task_struct *task[NR_TASKS];
extern struct task_struct *last_task_used_math;
extern struct task_struct *current;
extern long volatile jiffies;
extern long startup_time;

#define CURRENT_TIME (startup_time+jiffies/HZ)

extern void sleep_on(struct task_struct ** p);
extern void interruptible_sleep_on(struct task_struct ** p);
extern void wake_up(struct task_struct ** p);

/*

  • Entry into gdt where to find first TSS. 0-nul, 1-cs, 2-ds, 3-syscall
  • 4-TSS0, 5-LDT0, 6-TSS1 etc …
    /
    #define FIRST_TSS_ENTRY 4
    #define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)
    #define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
    #define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
    #define ltr(n) asm(“ltr %%ax”::“a” (_TSS(n)))
    #define lldt(n) asm(“lldt %%ax”::“a” (_LDT(n)))
    #define str(n)
    asm(“str %%ax\n\t”
    “subl %2,%%eax\n\t”
    “shrl $4,%%eax”
    :"=a" (n)
    :“a” (0),“i” (FIRST_TSS_ENTRY<<3))
    /
  • switch_to(n) should switch tasks to task nr n, first
  • checking that n isn’t the current task, in which case it does nothing.
  • This also clears the TS-flag if the task we switched to has used
  • tha math co-processor latest.
    /
    #define switch_to(n) {
    struct {long a,b;} __tmp;
    asm(“cmpl %%ecx,_current\n\t”
    “je 1f\n\t”
    “xchgl %%ecx,_current\n\t”
    “movw %%dx,%1\n\t”
    “ljmp %0\n\t”
    “cmpl %%ecx,%2\n\t”
    “jne 1f\n\t”
    “clts\n”
    “1:”
    ::“m” (
    &__tmp.a),“m” (*&__tmp.b),
    “m” (last_task_used_math),“d” _TSS(n),“c” ((long) task[n]));
    }

#define PAGE_ALIGN(n) (((n)+0xfff)&0xfffff000)

#define _set_base(addr,base)
asm(“movw %%dx,%0\n\t”
“rorl $16,%%edx\n\t”
“movb %%dl,%1\n\t”
“movb %%dh,%2”
::“m” (((addr)+2)),
“m” (
((addr)+4)),
“m” (*((addr)+7)),
“d” (base)
:“dx”)

#define _set_limit(addr,limit)
asm(“movw %%dx,%0\n\t”
“rorl $16,%%edx\n\t”
“movb %1,%%dh\n\t”
“andb $0xf0,%%dh\n\t”
“orb %%dh,%%dl\n\t”
“movb %%dl,%1”
::“m” ((addr)),
“m” (
((addr)+6)),
“d” (limit)
:“dx”)

#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )
#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )

#define _get_base(addr) ({
unsigned long __base;
asm(“movb %3,%%dh\n\t”
“movb %2,%%dl\n\t”
“shll $16,%%edx\n\t”
“movw %1,%%dx”
:"=d" (__base)
:“m” (((addr)+2)),
“m” (
((addr)+4)),
“m” (*((addr)+7)));
__base;})

#define get_base(ldt) _get_base( ((char *)&(ldt)) )

#define get_limit(segment) ({
unsigned long __limit;
asm(“lsll %1,%0\n\tincl %0”:"=r" (__limit):“r” (segment));
__limit;})

#endif



sys.h
extern int sys_setup();
extern int sys_exit();
extern int sys_fork();
extern int sys_read();
extern int sys_write();
extern int sys_open();
extern int sys_close();
extern int sys_waitpid();
extern int sys_creat();
extern int sys_link();
extern int sys_unlink();
extern int sys_execve();
extern int sys_chdir();
extern int sys_time();
extern int sys_mknod();
extern int sys_chmod();
extern int sys_chown();
extern int sys_break();
extern int sys_stat();
extern int sys_lseek();
extern int sys_getpid();
extern int sys_mount();
extern int sys_umount();
extern int sys_setuid();
extern int sys_getuid();
extern int sys_stime();
extern int sys_ptrace();
extern int sys_alarm();
extern int sys_fstat();
extern int sys_pause();
extern int sys_utime();
extern int sys_stty();
extern int sys_gtty();
extern int sys_access();
extern int sys_nice();
extern int sys_ftime();
extern int sys_sync();
extern int sys_kill();
extern int sys_rename();
extern int sys_mkdir();
extern int sys_rmdir();
extern int sys_dup();
extern int sys_pipe();
extern int sys_times();
extern int sys_prof();
extern int sys_brk();
extern int sys_setgid();
extern int sys_getgid();
extern int sys_signal();
extern int sys_geteuid();
extern int sys_getegid();
extern int sys_acct();
extern int sys_phys();
extern int sys_lock();
extern int sys_ioctl();
extern int sys_fcntl();
extern int sys_mpx();
extern int sys_setpgid();
extern int sys_ulimit();
extern int sys_uname();
extern int sys_umask();
extern int sys_chroot();
extern int sys_ustat();
extern int sys_dup2();
extern int sys_getppid();
extern int sys_getpgrp();
extern int sys_setsid();

fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod,
sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount,
sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access,
sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,
sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
sys_getpgrp,sys_setsid};



tty.h
/*

  • ‘tty.h’ defines some structures used by tty_io.c and some defines.
  • NOTE! Don’t touch this without checking that nothing in rs_io.s or
  • con_io.s breaks. Some constants are hardwired into the system (mainly
  • offsets into ‘tty_queue’
    */

#ifndef _TTY_H
#define _TTY_H

#include <termios.h>

#define TTY_BUF_SIZE 1024

struct tty_queue {
unsigned long data;
unsigned long head;
unsigned long tail;
struct task_struct * proc_list;
char buf[TTY_BUF_SIZE];
};

#define INC(a) ((a) = ((a)+1) & (TTY_BUF_SIZE-1))
#define DEC(a) ((a) = ((a)-1) & (TTY_BUF_SIZE-1))
#define EMPTY(a) ((a).head == (a).tail)
#define LEFT(a) (((a).tail-(a).head-1)&(TTY_BUF_SIZE-1))
#define LAST(a) ((a).buf[(TTY_BUF_SIZE-1)&((a).head-1)])
#define FULL(a) (!LEFT(a))
#define CHARS(a) (((a).head-(a).tail)&(TTY_BUF_SIZE-1))
#define GETCH(queue,c)
(void)({c=(queue).buf[(queue).tail];INC((queue).tail);})
#define PUTCH(c,queue)
(void)({(queue).buf[(queue).head]=©;INC((queue).head);})

#define EOF_CHAR(tty) ((tty)->termios.c_cc[VEOF])
#define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR])
#define STOP_CHAR(tty) ((tty)->termios.c_cc[VSTOP])
#define START_CHAR(tty) ((tty)->termios.c_cc[VSTART])
#define ERASE_CHAR(tty) ((tty)->termios.c_cc[VERASE])

struct tty_struct {
struct termios termios;
int pgrp;
int stopped;
void (*write)(struct tty_struct * tty);
struct tty_queue read_q;
struct tty_queue write_q;
struct tty_queue secondary;
};

extern struct tty_struct tty_table[];

/* intr=^C quit=^| erase=del kill=^U
eof=^D vtime=\0 vmin=\1 sxtc=\0
start=^Q stop=^S susp=^Y eol=\0
reprint=^R discard=^U werase=^W lnext=^V
eol2=\0
*/
#define INIT_C_CC “\003\034\177\025\004\0\1\0\021\023\031\0\022\017\027\026\0”

void rs_init(void);
void con_init(void);
void tty_init(void);

int tty_read(unsigned c, char * buf, int n);
int tty_write(unsigned c, char * buf, int n);

void rs_write(struct tty_struct * tty);
void con_write(struct tty_struct * tty);

void copy_to_cooked(struct tty_struct * tty);

#endif



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Linux 互斥锁主要是通过内核中的 mutex API 实现的。下面是一个简单的互斥锁示例代码: ``` #include <pthread.h> #include <stdio.h> pthread_mutex_t mutex; void *thread_func(void *arg) { pthread_mutex_lock(&mutex); // 加锁 printf("Thread %d is in critical section\n", *((int*)arg)); pthread_mutex_unlock(&mutex); // 解锁 return NULL; } int main() { pthread_t tid[2]; int thread_num[2] = {1, 2}; pthread_mutex_init(&mutex, NULL); // 初始化互斥锁 pthread_create(&tid[0], NULL, thread_func, &thread_num[0]); pthread_create(&tid[1], NULL, thread_func, &thread_num[1]); pthread_join(tid[0], NULL); pthread_join(tid[1], NULL); pthread_mutex_destroy(&mutex); // 销毁互斥锁 return 0; } ``` 在该示例中,我们首先使用 `pthread_mutex_init()` 初始化互斥锁并创建两个线程。线程函数 `thread_func()` 中,通过 `pthread_mutex_lock()` 和 `pthread_mutex_unlock()` 来进行锁的加解锁操作。 下面是互斥锁的源代码分析: 互斥锁的数据结构定义如下: ``` typedef struct { int count; int owner; struct futex q; } mutex_t; ``` 其中,`count` 表示锁的计数,`owner` 表示当前持有锁的线程 ID,`q` 表示等待队列。 下面是互斥锁的加锁操作 `mutex_lock()` 的源代码: ``` void mutex_lock(mutex_t *lock) { if (atomic_inc_return(&lock->count) == 1) { lock->owner = current_thread_id(); return; } if (lock->owner == current_thread_id()) return; futex_down(&lock->q, lock->count, current_thread_id()); lock->owner = current_thread_id(); } ``` 在该函数中,我们首先通过原子加操作 `atomic_inc_return()` 来将 `lock->count` 加 1,并判断锁是否已经被占用。如果是第一个线程获取锁,那么直接将 `lock->owner` 设置为当前线程 ID 并返回,否则则将当前线程加入到等待队列中并阻塞。 下面是互斥锁的解锁操作 `mutex_unlock()` 的源代码: ``` void mutex_unlock(mutex_t *lock) { if (!atomic_dec_return(&lock->count)) { lock->owner = 0; futex_up(&lock->q, 1); } } ``` 在该函数中,我们首先通过原子减操作 `atomic_dec_return()` 将 `lock->count` 减 1,并判断是否为 0。如果为 0,则将 `lock->owner` 设置为 0 并唤醒等待队列中的一个线程。 综上所述,Linux 互斥锁主要是通过内核中的 mutex API 实现的。在加锁操作中,通过原子操作对计数进行加一,并根据计数判断是否需要将当前线程加入到等待队列中;在解锁操作中,通过原子操作对计数进行减一,并根据计数判断是否需要唤醒等待队列中的一个线程。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

低调的小哥哥

你的关注就是我为你服务的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值