跳到主要內容

尾聲-一些瑣碎的事兒

問題一:我們的系統每次啟動都是「全新」的,上次建立的文件到下一次啟動就不見了。
問題二:每次都會執行一次解開 cmd.tar 的操作。
問題三:再一次解壓縮時,可能已有包含的檔案了



讓 mkfs() 只執行一次

fs/main.c

/*************************************************************************//**
 *****************************************************************************
 * @file   main.c
 * @brief
 * @author Forrest Y. Yu
 * @date   2007
 *****************************************************************************
 *****************************************************************************/

#include "type.h"
#include "config.h"
#include "stdio.h"
#include "const.h"
#include "protect.h"
#include "string.h"
#include "fs.h"
#include "proc.h"
#include "tty.h"
#include "console.h"
#include "global.h"
#include "proto.h"

#include "hd.h"

PRIVATE void init_fs();
PRIVATE void mkfs();
PRIVATE void read_super_block(int dev);
PRIVATE int fs_fork();
PRIVATE int fs_exit();

/*****************************************************************************
 *                                task_fs
 *****************************************************************************/
/**
 * <Ring 1> The main loop of TASK FS.
 *
 *****************************************************************************/
PUBLIC void task_fs()
{
 printl("{FS} Task FS begins.\n");

 init_fs();

 while (1) {
  send_recv(RECEIVE, ANY, &fs_msg);

  int msgtype = fs_msg.type;
  int src = fs_msg.source;
  pcaller = &proc_table[src];

  switch (msgtype) {
  case OPEN:
   fs_msg.FD = do_open();
   break;
  case CLOSE:
   fs_msg.RETVAL = do_close();
   break;
  case READ:
  case WRITE:
   fs_msg.CNT = do_rdwt();
   break;
  case UNLINK:
   fs_msg.RETVAL = do_unlink();
   break;
  case RESUME_PROC:
   src = fs_msg.PROC_NR;
   break;
  case FORK:
   fs_msg.RETVAL = fs_fork();
   break;
  case EXIT:
   fs_msg.RETVAL = fs_exit();
   break;
  case LSEEK:
   fs_msg.OFFSET = do_lseek();
   break;
  case STAT:
   fs_msg.RETVAL = do_stat();
   break;
  default:
   dump_msg("FS::unknown message:", &fs_msg);
   assert(0);
   break;
  }

#ifdef ENABLE_DISK_LOG
  char * msg_name[128];
  msg_name[OPEN]   = "OPEN";
  msg_name[CLOSE]  = "CLOSE";
  msg_name[READ]   = "READ";
  msg_name[WRITE]  = "WRITE";
  msg_name[LSEEK]  = "LSEEK";
  msg_name[UNLINK] = "UNLINK";
  msg_name[FORK]   = "FORK";
  msg_name[EXIT]   = "EXIT";
  msg_name[STAT]   = "STAT";

  switch (msgtype) {
  case UNLINK:
   dump_fd_graph("%s just finished. (pid:%d)",
          msg_name[msgtype], src);
   //panic("");
  case OPEN:
  case CLOSE:
  case READ:
  case WRITE:
  case FORK:
  case EXIT:
  case LSEEK:
  case STAT:
   break;
  case RESUME_PROC:
   break;
  default:
   assert(0);
  }
#endif

  /* reply */
  if (fs_msg.type != SUSPEND_PROC) {
   fs_msg.type = SYSCALL_RET;
   send_recv(SEND, src, &fs_msg);
  }
 }
}

/*****************************************************************************
 *                                init_fs
 *****************************************************************************/
/**
 * <Ring 1> Do some preparation.
 *
 *****************************************************************************/
PRIVATE void init_fs()
{
 int i;

 /* f_desc_table[] */
 for (i = 0; i < NR_FILE_DESC; i++)
  memset(&f_desc_table[i], 0, sizeof(struct file_desc));

 /* inode_table[] */
 for (i = 0; i < NR_INODE; i++)
  memset(&inode_table[i], 0, sizeof(struct inode));

 /* super_block[] */
 struct super_block * sb = super_block;
 for (; sb < &super_block[NR_SUPER_BLOCK]; sb++)
  sb->sb_dev = NO_DEV;

 /* open the device: hard disk */
 MESSAGE driver_msg;
 driver_msg.type = DEV_OPEN;
 driver_msg.DEVICE = MINOR(ROOT_DEV);
 assert(dd_map[MAJOR(ROOT_DEV)].driver_nr != INVALID_DRIVER);
 send_recv(BOTH, dd_map[MAJOR(ROOT_DEV)].driver_nr, &driver_msg);

 /* read the super block of ROOT DEVICE */
 RD_SECT(ROOT_DEV, 1);

 sb = (struct super_block *)fsbuf;
 if (sb->magic != MAGIC_V1) {
  printl("{FS} mkfs\n");
  mkfs(); /* make FS */
 }

 /* load super block of ROOT */
 read_super_block(ROOT_DEV);

 sb = get_super_block(ROOT_DEV);
 assert(sb->magic == MAGIC_V1);

 root_inode = get_inode(ROOT_DEV, ROOT_INODE);
}

/*****************************************************************************
 *                                mkfs
 *****************************************************************************/
/**
 * <Ring 1> Make a available Orange'S FS in the disk. It will
 *          - Write a super block to sector 1.
 *          - Create three special files: dev_tty0, dev_tty1, dev_tty2
 *          - Create a file cmd.tar
 *          - Create the inode map
 *          - Create the sector map
 *          - Create the inodes of the files
 *          - Create `/', the root directory
 *****************************************************************************/
PRIVATE void mkfs()
{
 MESSAGE driver_msg;
 int i, j;

 /************************/
 /*      super block     */
 /************************/
 /* get the geometry of ROOTDEV */
 struct part_info geo;
 driver_msg.type  = DEV_IOCTL;
 driver_msg.DEVICE = MINOR(ROOT_DEV);
 driver_msg.REQUEST = DIOCTL_GET_GEO;
 driver_msg.BUF  = &geo;
 driver_msg.PROC_NR = TASK_FS;
 assert(dd_map[MAJOR(ROOT_DEV)].driver_nr != INVALID_DRIVER);
 send_recv(BOTH, dd_map[MAJOR(ROOT_DEV)].driver_nr, &driver_msg);

 printl("{FS} dev size: 0x%x sectors\n", geo.size);

 int bits_per_sect = SECTOR_SIZE * 8; /* 8 bits per byte */
 /* generate a super block */
 struct super_block sb;
 sb.magic   = MAGIC_V1; /* 0x111 */
 sb.nr_inodes   = bits_per_sect;
 sb.nr_inode_sects = sb.nr_inodes * INODE_SIZE / SECTOR_SIZE;
 sb.nr_sects   = geo.size; /* partition size in sector */
 sb.nr_imap_sects  = 1;
 sb.nr_smap_sects  = sb.nr_sects / bits_per_sect + 1;
 sb.n_1st_sect   = 1 + 1 +   /* boot sector & super block */
  sb.nr_imap_sects + sb.nr_smap_sects + sb.nr_inode_sects;
 sb.root_inode   = ROOT_INODE;
 sb.inode_size   = INODE_SIZE;
 struct inode x;
 sb.inode_isize_off= (int)&x.i_size - (int)&x;
 sb.inode_start_off= (int)&x.i_start_sect - (int)&x;
 sb.dir_ent_size   = DIR_ENTRY_SIZE;
 struct dir_entry de;
 sb.dir_ent_inode_off = (int)&de.inode_nr - (int)&de;
 sb.dir_ent_fname_off = (int)&de.name - (int)&de;

 memset(fsbuf, 0x90, SECTOR_SIZE);
 memcpy(fsbuf, &sb, SUPER_BLOCK_SIZE);

 /* write the super block */
 WR_SECT(ROOT_DEV, 1);

 printl("{FS} devbase:0x%x00, sb:0x%x00, imap:0x%x00, smap:0x%x00\n"
        "        inodes:0x%x00, 1st_sector:0x%x00\n",
        geo.base * 2,
        (geo.base + 1) * 2,
        (geo.base + 1 + 1) * 2,
        (geo.base + 1 + 1 + sb.nr_imap_sects) * 2,
        (geo.base + 1 + 1 + sb.nr_imap_sects + sb.nr_smap_sects) * 2,
        (geo.base + sb.n_1st_sect) * 2);

 /************************/
 /*       inode map      */
 /************************/
 memset(fsbuf, 0, SECTOR_SIZE);
 for (i = 0; i < (NR_CONSOLES + 3); i++)
  fsbuf[0] |= 1 << i;

 assert(fsbuf[0] == 0x3F);/* 0011 1111 :
      *   || ||||
      *   || |||`--- bit 0 : reserved
      *   || ||`---- bit 1 : the first inode,
      *   || ||              which indicates `/'
      *   || |`----- bit 2 : /dev_tty0
      *   || `------ bit 3 : /dev_tty1
      *   |`-------- bit 4 : /dev_tty2
      *   `--------- bit 5 : /cmd.tar
      */
 WR_SECT(ROOT_DEV, 2);

 /************************/
 /*      secter map      */
 /************************/
 memset(fsbuf, 0, SECTOR_SIZE);
 int nr_sects = NR_DEFAULT_FILE_SECTS + 1;
 /*             ~~~~~~~~~~~~~~~~~~~|~   |
  *                                |    `--- bit 0 is reserved
  *                                `-------- for `/'
  */
 for (i = 0; i < nr_sects / 8; i++)
  fsbuf[i] = 0xFF;

 for (j = 0; j < nr_sects % 8; j++)
  fsbuf[i] |= (1 << j);

 WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects);

 /* zeromemory the rest sector-map */
 memset(fsbuf, 0, SECTOR_SIZE);
 for (i = 1; i < sb.nr_smap_sects; i++)
  WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + i);

 /* cmd.tar */
 /* make sure it'll not be overwritten by the disk log */
 assert(INSTALL_START_SECT + INSTALL_NR_SECTS <
        sb.nr_sects - NR_SECTS_FOR_LOG);
 int bit_offset = INSTALL_START_SECT -
  sb.n_1st_sect + 1; /* sect M <-> bit (M - sb.n_1stsect + 1) */
 int bit_off_in_sect = bit_offset % (SECTOR_SIZE * 8);
 int bit_left = INSTALL_NR_SECTS;
 int cur_sect = bit_offset / (SECTOR_SIZE * 8);
 RD_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect);
 while (bit_left) {
  int byte_off = bit_off_in_sect / 8;
  /* this line is ineffecient in a loop, but I don't care */
  fsbuf[byte_off] |= 1 << (bit_off_in_sect % 8);
  bit_left--;
  bit_off_in_sect++;
  if (bit_off_in_sect == (SECTOR_SIZE * 8)) {
   WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect);
   cur_sect++;
   RD_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect);
   bit_off_in_sect = 0;
  }
 }
 WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect);

 /************************/
 /*       inodes         */
 /************************/
 /* inode of `/' */
 memset(fsbuf, 0, SECTOR_SIZE);
 struct inode * pi = (struct inode*)fsbuf;
 pi->i_mode = I_DIRECTORY;
 pi->i_size = DIR_ENTRY_SIZE * 5; /* 5 files:
       * `.',
       * `dev_tty0', `dev_tty1', `dev_tty2',
       * `cmd.tar'
       */
 pi->i_start_sect = sb.n_1st_sect;
 pi->i_nr_sects = NR_DEFAULT_FILE_SECTS;
 /* inode of `/dev_tty0~2' */
 for (i = 0; i < NR_CONSOLES; i++) {
  pi = (struct inode*)(fsbuf + (INODE_SIZE * (i + 1)));
  pi->i_mode = I_CHAR_SPECIAL;
  pi->i_size = 0;
  pi->i_start_sect = MAKE_DEV(DEV_CHAR_TTY, i);
  pi->i_nr_sects = 0;
 }
 /* inode of `/cmd.tar' */
 pi = (struct inode*)(fsbuf + (INODE_SIZE * (NR_CONSOLES + 1)));
 pi->i_mode = I_REGULAR;
 pi->i_size = INSTALL_NR_SECTS * SECTOR_SIZE;
 pi->i_start_sect = INSTALL_START_SECT;
 pi->i_nr_sects = INSTALL_NR_SECTS;
 WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + sb.nr_smap_sects);

 /************************/
 /*          `/'         */
 /************************/
 memset(fsbuf, 0, SECTOR_SIZE);
 struct dir_entry * pde = (struct dir_entry *)fsbuf;

 pde->inode_nr = 1;
 strcpy(pde->name, ".");

 /* dir entries of `/dev_tty0~2' */
 for (i = 0; i < NR_CONSOLES; i++) {
  pde++;
  pde->inode_nr = i + 2; /* dev_tty0's inode_nr is 2 */
  sprintf(pde->name, "dev_tty%d", i);
 }
 (++pde)->inode_nr = NR_CONSOLES + 2;
 sprintf(pde->name, "cmd.tar", i);
 WR_SECT(ROOT_DEV, sb.n_1st_sect);
}

/*****************************************************************************
 *                                rw_sector
 *****************************************************************************/
/**
 * <Ring 1> R/W a sector via messaging with the corresponding driver.
 *
 * @param io_type  DEV_READ or DEV_WRITE
 * @param dev      device nr
 * @param pos      Byte offset from/to where to r/w.
 * @param bytes    r/w count in bytes.
 * @param proc_nr  To whom the buffer belongs.
 * @param buf      r/w buffer.
 *
 * @return Zero if success.
 *****************************************************************************/
PUBLIC int rw_sector(int io_type, int dev, u64 pos, int bytes, int proc_nr,
       void* buf)
{
 MESSAGE driver_msg;

 driver_msg.type  = io_type;
 driver_msg.DEVICE = MINOR(dev);
 driver_msg.POSITION = pos;
 driver_msg.BUF  = buf;
 driver_msg.CNT  = bytes;
 driver_msg.PROC_NR = proc_nr;
 assert(dd_map[MAJOR(dev)].driver_nr != INVALID_DRIVER);
 send_recv(BOTH, dd_map[MAJOR(dev)].driver_nr, &driver_msg);

 return 0;
}


/*****************************************************************************
 *                                read_super_block
 *****************************************************************************/
/**
 * <Ring 1> Read super block from the given device then write it into a free
 *          super_block[] slot.
 *
 * @param dev  From which device the super block comes.
 *****************************************************************************/
PRIVATE void read_super_block(int dev)
{
 int i;
 MESSAGE driver_msg;

 driver_msg.type  = DEV_READ;
 driver_msg.DEVICE = MINOR(dev);
 driver_msg.POSITION = SECTOR_SIZE * 1;
 driver_msg.BUF  = fsbuf;
 driver_msg.CNT  = SECTOR_SIZE;
 driver_msg.PROC_NR = TASK_FS;
 assert(dd_map[MAJOR(dev)].driver_nr != INVALID_DRIVER);
 send_recv(BOTH, dd_map[MAJOR(dev)].driver_nr, &driver_msg);

 /* find a free slot in super_block[] */
 for (i = 0; i < NR_SUPER_BLOCK; i++)
  if (super_block[i].sb_dev == NO_DEV)
   break;
 if (i == NR_SUPER_BLOCK)
  panic("super_block slots used up");

 assert(i == 0); /* currently we use only the 1st slot */

 struct super_block * psb = (struct super_block *)fsbuf;

 super_block[i] = *psb;
 super_block[i].sb_dev = dev;
}


/*****************************************************************************
 *                                get_super_block
 *****************************************************************************/
/**
 * <Ring 1> Get the super block from super_block[].
 *
 * @param dev Device nr.
 *
 * @return Super block ptr.
 *****************************************************************************/
PUBLIC struct super_block * get_super_block(int dev)
{
 struct super_block * sb = super_block;
 for (; sb < &super_block[NR_SUPER_BLOCK]; sb++)
  if (sb->sb_dev == dev)
   return sb;

 panic("super block of devie %d not found.\n", dev);

 return 0;
}


/*****************************************************************************
 *                                get_inode
 *****************************************************************************/
/**
 * <Ring 1> Get the inode ptr of given inode nr. A cache -- inode_table[] -- is
 * maintained to make things faster. If the inode requested is already there,
 * just return it. Otherwise the inode will be read from the disk.
 *
 * @param dev Device nr.
 * @param num I-node nr.
 *
 * @return The inode ptr requested.
 *****************************************************************************/
PUBLIC struct inode * get_inode(int dev, int num)
{
 if (num == 0)
  return 0;

 struct inode * p;
 struct inode * q = 0;
 for (p = &inode_table[0]; p < &inode_table[NR_INODE]; p++) {
  if (p->i_cnt) { /* not a free slot */
   if ((p->i_dev == dev) && (p->i_num == num)) {
    /* this is the inode we want */
    p->i_cnt++;
    return p;
   }
  }
  else {  /* a free slot */
   if (!q) /* q hasn't been assigned yet */
    q = p; /* q <- the 1st free slot */
  }
 }

 if (!q)
  panic("the inode table is full");

 q->i_dev = dev;
 q->i_num = num;
 q->i_cnt = 1;

 struct super_block * sb = get_super_block(dev);
 int blk_nr = 1 + 1 + sb->nr_imap_sects + sb->nr_smap_sects +
  ((num - 1) / (SECTOR_SIZE / INODE_SIZE));
 RD_SECT(dev, blk_nr);
 struct inode * pinode =
  (struct inode*)((u8*)fsbuf +
    ((num - 1 ) % (SECTOR_SIZE / INODE_SIZE))
     * INODE_SIZE);
 q->i_mode = pinode->i_mode;
 q->i_size = pinode->i_size;
 q->i_start_sect = pinode->i_start_sect;
 q->i_nr_sects = pinode->i_nr_sects;
 return q;
}

/*****************************************************************************
 *                                put_inode
 *****************************************************************************/
/**
 * Decrease the reference nr of a slot in inode_table[]. When the nr reaches
 * zero, it means the inode is not used any more and can be overwritten by
 * a new inode.
 *
 * @param pinode I-node ptr.
 *****************************************************************************/
PUBLIC void put_inode(struct inode * pinode)
{
 assert(pinode->i_cnt > 0);
 pinode->i_cnt--;
}

/*****************************************************************************
 *                                sync_inode
 *****************************************************************************/
/**
 * <Ring 1> Write the inode back to the disk. Commonly invoked as soon as the
 *          inode is changed.
 *
 * @param p I-node ptr.
 *****************************************************************************/
PUBLIC void sync_inode(struct inode * p)
{
 struct inode * pinode;
 struct super_block * sb = get_super_block(p->i_dev);
 int blk_nr = 1 + 1 + sb->nr_imap_sects + sb->nr_smap_sects +
  ((p->i_num - 1) / (SECTOR_SIZE / INODE_SIZE));
 RD_SECT(p->i_dev, blk_nr);
 pinode = (struct inode*)((u8*)fsbuf +
     (((p->i_num - 1) % (SECTOR_SIZE / INODE_SIZE))
      * INODE_SIZE));
 pinode->i_mode = p->i_mode;
 pinode->i_size = p->i_size;
 pinode->i_start_sect = p->i_start_sect;
 pinode->i_nr_sects = p->i_nr_sects;
 WR_SECT(p->i_dev, blk_nr);
}

/*****************************************************************************
 *                                fs_fork
 *****************************************************************************/
/**
 * Perform the aspects of fork() that relate to files.
 *
 * @return Zero if success, otherwise a negative integer.
 *****************************************************************************/
PRIVATE int fs_fork()
{
 int i;
 struct proc* child = &proc_table[fs_msg.PID];
 for (i = 0; i < NR_FILES; i++) {
  if (child->filp[i]) {
   child->filp[i]->fd_cnt++;
   child->filp[i]->fd_inode->i_cnt++;
  }
 }

 return 0;
}


/*****************************************************************************
 *                                fs_exit
 *****************************************************************************/
/**
 * Perform the aspects of exit() that relate to files.
 *
 * @return Zero if success.
 *****************************************************************************/
PRIVATE int fs_exit()
{
 int i;
 struct proc* p = &proc_table[fs_msg.PID];
 for (i = 0; i < NR_FILES; i++) {
  if (p->filp[i]) {
   /* release the inode */
   p->filp[i]->fd_inode->i_cnt--;
   /* release the file desc slot */
   if (--p->filp[i]->fd_cnt == 0)
    p->filp[i]->fd_inode = 0;
   p->filp[i] = 0;
  }
 }
 return 0;
}

修改 untar()

kernel/main.c

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                            main.c
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                                                    Forrest Yu, 2005
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

#include "type.h"
#include "stdio.h"
#include "const.h"
#include "protect.h"
#include "string.h"
#include "fs.h"
#include "proc.h"
#include "tty.h"
#include "console.h"
#include "global.h"
#include "proto.h"


/*****************************************************************************
 *                               kernel_main
 *****************************************************************************/
/**
 * jmp from kernel.asm::_start.
 *
 *****************************************************************************/
PUBLIC int kernel_main()
{
 disp_str("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");

 int i, j, eflags, prio;
        u8  rpl;
        u8  priv; /* privilege */

 struct task * t;
 struct proc * p = proc_table;

 char * stk = task_stack + STACK_SIZE_TOTAL;

 for (i = 0; i < NR_TASKS + NR_PROCS; i++,p++,t++) {
  if (i >= NR_TASKS + NR_NATIVE_PROCS) {
   p->p_flags = FREE_SLOT;
   continue;
  }

         if (i < NR_TASKS) {     /* TASK */
                        t = task_table + i;
                        priv = PRIVILEGE_TASK;
                        rpl     = RPL_TASK;
                        eflags  = 0x1202;/* IF=1, IOPL=1, bit 2 is always 1 */
   prio    = 15;
                }
                else {                  /* USER PROC */
                        t = user_proc_table + (i - NR_TASKS);
                        priv = PRIVILEGE_USER;
                        rpl     = RPL_USER;
                        eflags  = 0x202; /* IF=1, bit 2 is always 1 */
   prio    = 5;
                }

  strcpy(p->name, t->name); /* name of the process */
  p->p_parent = NO_TASK;

  if (strcmp(t->name, "INIT") != 0) {
   p->ldts[INDEX_LDT_C]  = gdt[SELECTOR_KERNEL_CS >> 3];
   p->ldts[INDEX_LDT_RW] = gdt[SELECTOR_KERNEL_DS >> 3];

   /* change the DPLs */
   p->ldts[INDEX_LDT_C].attr1  = DA_C   | priv << 5;
   p->ldts[INDEX_LDT_RW].attr1 = DA_DRW | priv << 5;
  }
  else {  /* INIT process */
   unsigned int k_base;
   unsigned int k_limit;
   int ret = get_kernel_map(&k_base, &k_limit);
   assert(ret == 0);
   init_desc(&p->ldts[INDEX_LDT_C],
      0, /* bytes before the entry point
          * are useless (wasted) for the
          * INIT process, doesn't matter
          */
      (k_base + k_limit) >> LIMIT_4K_SHIFT,
      DA_32 | DA_LIMIT_4K | DA_C | priv << 5);

   init_desc(&p->ldts[INDEX_LDT_RW],
      0, /* bytes before the entry point
          * are useless (wasted) for the
          * INIT process, doesn't matter
          */
      (k_base + k_limit) >> LIMIT_4K_SHIFT,
      DA_32 | DA_LIMIT_4K | DA_DRW | priv << 5);
  }

  p->regs.cs = INDEX_LDT_C << 3 | SA_TIL | rpl;
  p->regs.ds =
   p->regs.es =
   p->regs.fs =
   p->regs.ss = INDEX_LDT_RW << 3 | SA_TIL | rpl;
  p->regs.gs = (SELECTOR_KERNEL_GS & SA_RPL_MASK) | rpl;
  p->regs.eip = (u32)t->initial_eip;
  p->regs.esp = (u32)stk;
  p->regs.eflags = eflags;

  p->ticks = p->priority = prio;

  p->p_flags = 0;
  p->p_msg = 0;
  p->p_recvfrom = NO_TASK;
  p->p_sendto = NO_TASK;
  p->has_int_msg = 0;
  p->q_sending = 0;
  p->next_sending = 0;

  for (j = 0; j < NR_FILES; j++)
   p->filp[j] = 0;

  stk -= t->stacksize;
 }

 k_reenter = 0;
 ticks = 0;

 p_proc_ready = proc_table;

 init_clock();
        init_keyboard();

 restart();

 while(1){}
}


/*****************************************************************************
 *                                get_ticks
 *****************************************************************************/
PUBLIC int get_ticks()
{
 MESSAGE msg;
 reset_msg(&msg);
 msg.type = GET_TICKS;
 send_recv(BOTH, TASK_SYS, &msg);
 return msg.RETVAL;
}


/**
 * @struct posix_tar_header
 * Borrowed from GNU `tar'
 */
struct posix_tar_header
{    /* byte offset */
 char name[100];  /*   0 */
 char mode[8];  /* 100 */
 char uid[8];  /* 108 */
 char gid[8];  /* 116 */
 char size[12];  /* 124 */
 char mtime[12];  /* 136 */
 char chksum[8];  /* 148 */
 char typeflag;  /* 156 */
 char linkname[100]; /* 157 */
 char magic[6];  /* 257 */
 char version[2]; /* 263 */
 char uname[32];  /* 265 */
 char gname[32];  /* 297 */
 char devmajor[8]; /* 329 */
 char devminor[8]; /* 337 */
 char prefix[155]; /* 345 */
 /* 500 */
};

/*****************************************************************************
 *                                untar
 *****************************************************************************/
/**
 * Extract the tar file and store them.
 *
 * @param filename The tar file.
 *****************************************************************************/
void untar(const char * filename)
{
 printf("[extract `%s'\n", filename);
 int fd = open(filename, O_RDWR);
 assert(fd != -1);

 char buf[SECTOR_SIZE * 16];
 int chunk = sizeof(buf);
 int i = 0;
 int bytes = 0;

 while (1) {
  bytes = read(fd, buf, SECTOR_SIZE);
  assert(bytes == SECTOR_SIZE); /* size of a TAR file
            * must be multiple of 512
            */
  if (buf[0] == 0) {
   if (i == 0)
    printf("    need not unpack the file.\n");
   break;
  }
  i++;

  struct posix_tar_header * phdr = (struct posix_tar_header *)buf;

  /* calculate the file size */
  char * p = phdr->size;
  int f_len = 0;
  while (*p)
   f_len = (f_len * 8) + (*p++ - '0'); /* octal */

  int bytes_left = f_len;
  int fdout = open(phdr->name, O_CREAT | O_RDWR | O_TRUNC);
  if (fdout == -1) {
   printf("    failed to extract file: %s\n", phdr->name);
   printf(" aborted]\n");
   close(fd);
   return;
  }
  printf("    %s\n", phdr->name);
  while (bytes_left) {
   int iobytes = min(chunk, bytes_left);
   read(fd, buf,
        ((iobytes - 1) / SECTOR_SIZE + 1) * SECTOR_SIZE);
   bytes = write(fdout, buf, iobytes);
   assert(bytes == iobytes);
   bytes_left -= iobytes;
  }
  close(fdout);
 }

 if (i) {
  lseek(fd, 0, SEEK_SET);
  buf[0] = 0;
  bytes = write(fd, buf, 1);
  assert(bytes == 1);
 }

 close(fd);

 printf(" done, %d files extracted]\n", i);
}

/*****************************************************************************
 *                                shabby_shell
 *****************************************************************************/
/**
 * A very very simple shell.
 *
 * @param tty_name  TTY file name.
 *****************************************************************************/
void shabby_shell(const char * tty_name)
{
 int fd_stdin  = open(tty_name, O_RDWR);
 assert(fd_stdin  == 0);
 int fd_stdout = open(tty_name, O_RDWR);
 assert(fd_stdout == 1);

 char rdbuf[128];

 while (1) {
  write(1, "$ ", 2);
  int r = read(0, rdbuf, 70);
  rdbuf[r] = 0;

  int argc = 0;
  char * argv[PROC_ORIGIN_STACK];
  char * p = rdbuf;
  char * s;
  int word = 0;
  char ch;
  do {
   ch = *p;
   if (*p != ' ' && *p != 0 && !word) {
    s = p;
    word = 1;
   }
   if ((*p == ' ' || *p == 0) && word) {
    word = 0;
    argv[argc++] = s;
    *p = 0;
   }
   p++;
  } while(ch);
  argv[argc] = 0;

  int fd = open(argv[0], O_RDWR);
  if (fd == -1) {
   if (rdbuf[0]) {
    write(1, "{", 1);
    write(1, rdbuf, r);
    write(1, "}\n", 2);
   }
  }
  else {
   close(fd);
   int pid = fork();
   if (pid != 0) { /* parent */
    int s;
    wait(&s);
   }
   else { /* child */
    execv(argv[0], argv);
   }
  }
 }

 close(1);
 close(0);
}

/*****************************************************************************
 *                                Init
 *****************************************************************************/
/**
 * The hen.
 *
 *****************************************************************************/
void Init()
{
 int fd_stdin  = open("/dev_tty0", O_RDWR);
 assert(fd_stdin  == 0);
 int fd_stdout = open("/dev_tty0", O_RDWR);
 assert(fd_stdout == 1);

 printf("Init() is running ...\n");

 /* extract `cmd.tar' */
 untar("/cmd.tar");


 char * tty_list[] = {"/dev_tty1", "/dev_tty2"};

 int i;
 for (i = 0; i < sizeof(tty_list) / sizeof(tty_list[0]); i++) {
  int pid = fork();
  if (pid != 0) { /* parent process */
   printf("[parent is running, child pid:%d]\n", pid);
  }
  else { /* child process */
   printf("[child is running, pid:%d]\n", getpid());
   close(fd_stdin);
   close(fd_stdout);

   shabby_shell(tty_list[i]);
   assert(0);
  }
 }

 while (1) {
  int s;
  int child = wait(&s);
  printf("child (%d) exited with status: %d.\n", child, s);
 }

 assert(0);
}


/*======================================================================*
                               TestA
 *======================================================================*/
void TestA()
{
 for(;;);
}

/*======================================================================*
                               TestB
 *======================================================================*/
void TestB()
{
 for(;;);
}

/*======================================================================*
                               TestB
 *======================================================================*/
void TestC()
{
 for(;;);
}

/*****************************************************************************
 *                                panic
 *****************************************************************************/
PUBLIC void panic(const char *fmt, ...)
{
 int i;
 char buf[256];

 /* 4 is the size of fmt in the stack */
 va_list arg = (va_list)((char*)&fmt + 4);

 i = vsprintf(buf, fmt, arg);

 printl("%c !!panic!! %s", MAG_CH_PANIC, buf);

 /* should never arrive here */
 __asm__ __volatile__("ud2");
}

清除舊檔案,寫入新內容

fs/open.c

/*************************************************************************//**
 *****************************************************************************
 * @file   fs/open.c
 * The file contains:
 *   - do_open()
 *   - do_close()
 *   - do_lseek()
 *   - create_file()
 * @author Forrest Yu
 * @date   2007
 *****************************************************************************
 *****************************************************************************/

#include "type.h"
#include "stdio.h"
#include "const.h"
#include "protect.h"
#include "string.h"
#include "fs.h"
#include "proc.h"
#include "tty.h"
#include "console.h"
#include "global.h"
#include "keyboard.h"
#include "proto.h"

PRIVATE struct inode * create_file(char * path, int flags);
PRIVATE int alloc_imap_bit(int dev);
PRIVATE int alloc_smap_bit(int dev, int nr_sects_to_alloc);
PRIVATE struct inode * new_inode(int dev, int inode_nr, int start_sect);
PRIVATE void new_dir_entry(struct inode * dir_inode, int inode_nr, char * filename);

/*****************************************************************************
 *                                do_open
 *****************************************************************************/
/**
 * Open a file and return the file descriptor.
 *
 * @return File descriptor if successful, otherwise a negative error code.
 *****************************************************************************/
PUBLIC int do_open()
{
 int fd = -1;  /* return value */

 char pathname[MAX_PATH];

 /* get parameters from the message */
 int flags = fs_msg.FLAGS; /* access mode */
 int name_len = fs_msg.NAME_LEN; /* length of filename */
 int src = fs_msg.source; /* caller proc nr. */
 assert(name_len < MAX_PATH);
 phys_copy((void*)va2la(TASK_FS, pathname),
    (void*)va2la(src, fs_msg.PATHNAME),
    name_len);
 pathname[name_len] = 0;

 /* find a free slot in PROCESS::filp[] */
 int i;
 for (i = 0; i < NR_FILES; i++) {
  if (pcaller->filp[i] == 0) {
   fd = i;
   break;
  }
 }
 if ((fd < 0) || (fd >= NR_FILES))
  panic("filp[] is full (PID:%d)", proc2pid(pcaller));

 /* find a free slot in f_desc_table[] */
 for (i = 0; i < NR_FILE_DESC; i++)
  if (f_desc_table[i].fd_inode == 0)
   break;
 if (i >= NR_FILE_DESC)
  panic("f_desc_table[] is full (PID:%d)", proc2pid(pcaller));

 int inode_nr = search_file(pathname);

 struct inode * pin = 0;

 if (inode_nr == INVALID_INODE) { /* file not exists */
  if (flags & O_CREAT) {
   pin = create_file(pathname, flags);
  }
  else {
   printl("{FS} file not exists: %s\n", pathname);
   return -1;
  }
 }
 else if (flags & O_RDWR) { /* file exists */
  if ((flags & O_CREAT) && (!(flags & O_TRUNC))) {
   assert(flags == (O_RDWR | O_CREAT));
   printl("{FS} file exists: %s\n", pathname);
   return -1;
  }
  assert((flags ==  O_RDWR                     ) ||
         (flags == (O_RDWR | O_TRUNC          )) ||
         (flags == (O_RDWR | O_TRUNC | O_CREAT)));

  char filename[MAX_PATH];
  struct inode * dir_inode;
  if (strip_path(filename, pathname, &dir_inode) != 0)
   return -1;
  pin = get_inode(dir_inode->i_dev, inode_nr);
 }
 else { /* file exists, no O_RDWR flag */
  printl("{FS} file exists: %s\n", pathname);
  return -1;
 }

 if (flags & O_TRUNC) {
  assert(pin);
  pin->i_size = 0;
  sync_inode(pin);
 }

 if (pin) {
  /* connects proc with file_descriptor */
  pcaller->filp[fd] = &f_desc_table[i];

  /* connects file_descriptor with inode */
  f_desc_table[i].fd_inode = pin;

  f_desc_table[i].fd_mode = flags;
  f_desc_table[i].fd_cnt = 1;
  f_desc_table[i].fd_pos = 0;

  int imode = pin->i_mode & I_TYPE_MASK;

  if (imode == I_CHAR_SPECIAL) {
   MESSAGE driver_msg;
   driver_msg.type = DEV_OPEN;
   int dev = pin->i_start_sect;
   driver_msg.DEVICE = MINOR(dev);
   assert(MAJOR(dev) == 4);
   assert(dd_map[MAJOR(dev)].driver_nr != INVALID_DRIVER);
   send_recv(BOTH,
      dd_map[MAJOR(dev)].driver_nr,
      &driver_msg);
  }
  else if (imode == I_DIRECTORY) {
   assert(pin->i_num == ROOT_INODE);
  }
  else {
   assert(pin->i_mode == I_REGULAR);
  }
 }
 else {
  return -1;
 }

 return fd;
}

/*****************************************************************************
 *                                create_file
 *****************************************************************************/
/**
 * Create a file and return it's inode ptr.
 *
 * @param[in] path   The full path of the new file
 * @param[in] flags  Attribiutes of the new file
 *
 * @return           Ptr to i-node of the new file if successful, otherwise 0.
 *
 * @see open()
 * @see do_open()
 *****************************************************************************/
PRIVATE struct inode * create_file(char * path, int flags)
{
 char filename[MAX_PATH];
 struct inode * dir_inode;
 if (strip_path(filename, path, &dir_inode) != 0)
  return 0;

 int inode_nr = alloc_imap_bit(dir_inode->i_dev);
 int free_sect_nr = alloc_smap_bit(dir_inode->i_dev,
       NR_DEFAULT_FILE_SECTS);
 struct inode *newino = new_inode(dir_inode->i_dev, inode_nr,
      free_sect_nr);

 new_dir_entry(dir_inode, newino->i_num, filename);

 return newino;
}

/*****************************************************************************
 *                                do_close
 *****************************************************************************/
/**
 * Handle the message CLOSE.
 *
 * @return Zero if success.
 *****************************************************************************/
PUBLIC int do_close()
{
 int fd = fs_msg.FD;
 put_inode(pcaller->filp[fd]->fd_inode);
 if (--pcaller->filp[fd]->fd_cnt == 0)
  pcaller->filp[fd]->fd_inode = 0;
 pcaller->filp[fd] = 0;

 return 0;
}

/*****************************************************************************
 *                                do_lseek
 *****************************************************************************/
/**
 * Handle the message LSEEK.
 *
 * @return The new offset in bytes from the beginning of the file if successful,
 *         otherwise a negative number.
 *****************************************************************************/
PUBLIC int do_lseek()
{
 int fd = fs_msg.FD;
 int off = fs_msg.OFFSET;
 int whence = fs_msg.WHENCE;

 int pos = pcaller->filp[fd]->fd_pos;
 int f_size = pcaller->filp[fd]->fd_inode->i_size;

 switch (whence) {
 case SEEK_SET:
  pos = off;
  break;
 case SEEK_CUR:
  pos += off;
  break;
 case SEEK_END:
  pos = f_size + off;
  break;
 default:
  return -1;
  break;
 }
 if ((pos > f_size) || (pos < 0)) {
  return -1;
 }
 pcaller->filp[fd]->fd_pos = pos;
 return pos;
}

/*****************************************************************************
 *                                alloc_imap_bit
 *****************************************************************************/
/**
 * Allocate a bit in inode-map.
 *
 * @param dev  In which device the inode-map is located.
 *
 * @return  I-node nr.
 *****************************************************************************/
PRIVATE int alloc_imap_bit(int dev)
{
 int inode_nr = 0;
 int i, j, k;

 int imap_blk0_nr = 1 + 1; /* 1 boot sector & 1 super block */
 struct super_block * sb = get_super_block(dev);

 for (i = 0; i < sb->nr_imap_sects; i++) {
  RD_SECT(dev, imap_blk0_nr + i);

  for (j = 0; j < SECTOR_SIZE; j++) {
   /* skip `11111111' bytes */
   if (fsbuf[j] == 0xFF)
    continue;
   /* skip `1' bits */
   for (k = 0; ((fsbuf[j] >> k) & 1) != 0; k++) {}
   /* i: sector index; j: byte index; k: bit index */
   inode_nr = (i * SECTOR_SIZE + j) * 8 + k;
   fsbuf[j] |= (1 << k);
   /* write the bit to imap */
   WR_SECT(dev, imap_blk0_nr + i);
   break;
  }

  return inode_nr;
 }

 /* no free bit in imap */
 panic("inode-map is probably full.\n");

 return 0;
}

/*****************************************************************************
 *                                alloc_smap_bit
 *****************************************************************************/
/**
 * Allocate a bit in sector-map.
 *
 * @param dev  In which device the sector-map is located.
 * @param nr_sects_to_alloc  How many sectors are allocated.
 *
 * @return  The 1st sector nr allocated.
 *****************************************************************************/
PRIVATE int alloc_smap_bit(int dev, int nr_sects_to_alloc)
{
 /* int nr_sects_to_alloc = NR_DEFAULT_FILE_SECTS; */

 int i; /* sector index */
 int j; /* byte index */
 int k; /* bit index */

 struct super_block * sb = get_super_block(dev);

 int smap_blk0_nr = 1 + 1 + sb->nr_imap_sects;
 int free_sect_nr = 0;

 for (i = 0; i < sb->nr_smap_sects; i++) { /* smap_blk0_nr + i :
           current sect nr. */
  RD_SECT(dev, smap_blk0_nr + i);

  /* byte offset in current sect */
  for (j = 0; j < SECTOR_SIZE && nr_sects_to_alloc > 0; j++) {
   k = 0;
   if (!free_sect_nr) {
    /* loop until a free bit is found */
    if (fsbuf[j] == 0xFF) continue;
    for (; ((fsbuf[j] >> k) & 1) != 0; k++) {}
    free_sect_nr = (i * SECTOR_SIZE + j) * 8 +
     k - 1 + sb->n_1st_sect;
   }

   for (; k < 8; k++) { /* repeat till enough bits are set */
    assert(((fsbuf[j] >> k) & 1) == 0);
    fsbuf[j] |= (1 << k);
    if (--nr_sects_to_alloc == 0)
     break;
   }
  }

  if (free_sect_nr) /* free bit found, write the bits to smap */
   WR_SECT(dev, smap_blk0_nr + i);

  if (nr_sects_to_alloc == 0)
   break;
 }

 assert(nr_sects_to_alloc == 0);

 return free_sect_nr;
}

/*****************************************************************************
 *                                new_inode
 *****************************************************************************/
/**
 * Generate a new i-node and write it to disk.
 *
 * @param dev  Home device of the i-node.
 * @param inode_nr  I-node nr.
 * @param start_sect  Start sector of the file pointed by the new i-node.
 *
 * @return  Ptr of the new i-node.
 *****************************************************************************/
PRIVATE struct inode * new_inode(int dev, int inode_nr, int start_sect)
{
 struct inode * new_inode = get_inode(dev, inode_nr);

 new_inode->i_mode = I_REGULAR;
 new_inode->i_size = 0;
 new_inode->i_start_sect = start_sect;
 new_inode->i_nr_sects = NR_DEFAULT_FILE_SECTS;

 new_inode->i_dev = dev;
 new_inode->i_cnt = 1;
 new_inode->i_num = inode_nr;

 /* write to the inode array */
 sync_inode(new_inode);

 return new_inode;
}

/*****************************************************************************
 *                                new_dir_entry
 *****************************************************************************/
/**
 * Write a new entry into the directory.
 * 
 * @param dir_inode  I-node of the directory.
 * @param inode_nr   I-node nr of the new file.
 * @param filename   Filename of the new file.
 *****************************************************************************/
PRIVATE void new_dir_entry(struct inode *dir_inode,int inode_nr,char *filename)
{
 /* write the dir_entry */
 int dir_blk0_nr = dir_inode->i_start_sect;
 int nr_dir_blks = (dir_inode->i_size + SECTOR_SIZE) / SECTOR_SIZE;
 int nr_dir_entries =
  dir_inode->i_size / DIR_ENTRY_SIZE; /**
           * including unused slots
           * (the file has been
           * deleted but the slot
           * is still there)
           */
 int m = 0;
 struct dir_entry * pde;
 struct dir_entry * new_de = 0;

 int i, j;
 for (i = 0; i < nr_dir_blks; i++) {
  RD_SECT(dir_inode->i_dev, dir_blk0_nr + i);

  pde = (struct dir_entry *)fsbuf;
  for (j = 0; j < SECTOR_SIZE / DIR_ENTRY_SIZE; j++,pde++) {
   if (++m > nr_dir_entries)
    break;

   if (pde->inode_nr == 0) { /* it's a free slot */
    new_de = pde;
    break;
   }
  }
  if (m > nr_dir_entries ||/* all entries have been iterated or */
      new_de)              /* free slot is found */
   break;
 }
 if (!new_de) { /* reached the end of the dir */
  new_de = pde;
  dir_inode->i_size += DIR_ENTRY_SIZE;
 }
 new_de->inode_nr = inode_nr;
 strcpy(new_de->name, filename);

 /* write dir block -- ROOT dir block */
 WR_SECT(dir_inode->i_dev, dir_blk0_nr + i);

 /* update dir inode */
 sync_inode(dir_inode);
}

include/stdio.h

/*************************************************************************//**
 *****************************************************************************
 * @file   stdio.h
 * @brief
 * @author Forrest Y. Yu
 * @date   2008
 *****************************************************************************
 *****************************************************************************/

#ifndef _ORANGES_STDIO_H_
#define _ORANGES_STDIO_H_

#include "type.h"

/* the assert macro */
#define ASSERT
#ifdef ASSERT
void assertion_failure(char *exp, char *file, char *base_file, int line);
#define assert(exp)  if (exp) ; \
        else assertion_failure(#exp, __FILE__, __BASE_FILE__, __LINE__)
#else
#define assert(exp)
#endif

/* EXTERN */
#define EXTERN extern /* EXTERN is defined as extern except in global.c */

/* string */
#define STR_DEFAULT_LEN 1024

#define O_CREAT  1
#define O_RDWR  2
#define O_TRUNC  4

#define SEEK_SET 1
#define SEEK_CUR 2
#define SEEK_END 3

#define MAX_PATH 128

/**
 * @struct stat
 * @brief  File status, returned by syscall stat();
 */
struct stat {
 int st_dev;  /* major/minor device number */
 int st_ino;  /* i-node number */
 int st_mode;  /* file mode, protection bits, etc. */
 int st_rdev;  /* device ID (if special file) */
 int st_size;  /* file size */
};

/**
 * @struct time
 * @brief  RTC time from CMOS.
 */
struct time {
 u32 year;
 u32 month;
 u32 day;
 u32 hour;
 u32 minute;
 u32 second;
};

#define  BCD_TO_DEC(x)      ( (x >> 4) * 10 + (x & 0x0f) )

/*========================*
 * printf, printl, printx *
 *========================*
 *
 *   printf:
 *
 *           [send msg]                WRITE           DEV_WRITE
 *                      USER_PROC ------------→ FS -------------→ TTY
 *                              ↖______________↙↖_______________/
 *           [recv msg]             SYSCALL_RET       SYSCALL_RET
 *
 *----------------------------------------------------------------------
 *
 *   printl: variant-parameter-version printx
 *
 *          calls vsprintf, then printx (trap into kernel directly)
 *
 *----------------------------------------------------------------------
 *
 *   printx: low level print without using IPC
 *
 *                       trap directly
 *           USER_PROC -- -- -- -- -- --> KERNEL
 *
 *
 *----------------------------------------------------------------------
 */

/* printf.c */
PUBLIC  int     printf(const char *fmt, ...);
PUBLIC  int     printl(const char *fmt, ...);

/* vsprintf.c */
PUBLIC  int     vsprintf(char *buf, const char *fmt, va_list args);
PUBLIC int sprintf(char *buf, const char *fmt, ...);

/*--------*/
/* 庫函數 */
/*--------*/

#ifdef ENABLE_DISK_LOG
#define SYSLOG syslog
#endif

/* lib/open.c */
PUBLIC int open  (const char *pathname, int flags);

/* lib/close.c */
PUBLIC int close  (int fd);

/* lib/read.c */
PUBLIC int read  (int fd, void *buf, int count);

/* lib/write.c */
PUBLIC int write  (int fd, const void *buf, int count);

/* lib/lseek.c */
PUBLIC int lseek  (int fd, int offset, int whence);

/* lib/unlink.c */
PUBLIC int unlink  (const char *pathname);

/* lib/getpid.c */
PUBLIC int getpid  ();

/* lib/fork.c */
PUBLIC int fork  ();

/* lib/exit.c */
PUBLIC void exit  (int status);

/* lib/wait.c */
PUBLIC int wait  (int * status);

/* lib/exec.c */
PUBLIC int exec  (const char * path);
PUBLIC int execl  (const char * path, const char *arg, ...);
PUBLIC int execv  (const char * path, char * argv[]);

/* lib/stat.c */
PUBLIC int stat  (const char *path, struct stat *buf);

/* lib/syslog.c */
PUBLIC int syslog  (const char *fmt, ...);


#endif /* _ORANGES_STDIO_H_ */

執行畫面(必須執行兩次,第一次結束後設定 magic number,第二次即不會執行)

留言

這個網誌中的熱門文章

用 C# 批次控制 Word 合併列印

前由 我有全區的電話資料,問題在於我要依不同里別來製作出電話簿。結果如下圖: 單純採用合併列印無法達成我的需求。解決方法係用「功能變數」儲存上一個里別,與現在里別進行比較:若不同,則換頁。不過,這樣功能變數還蠻長的。最後,我還是採用 C# 來解決。 解決方案 用 C# 控制 WORD 中合併列印的「資料來源 Data Source」,給予不同里別的「sqlstatement」。迴圈處理不同的里別即可。但可預見其處理過程會很慢,不過還好,我可以不用在意它,有跑出結果即可。 程式碼 IList<string> areas = new List<string>() { "後壁", "侯伯", "嘉苳", "土溝", "嘉田", "嘉民", "菁豊", "崁頂", "後廍", "墨林", "菁寮", "新嘉", "頂長", "平安", "仕安", "竹新", "新東", "長安", "頂安", "福安", "烏樹" }; string root = @"D:\"; // 根目錄 string data = root + @"\data.docm"; // 資料檔(即資料來源) string template = root + @"\template.docx"; // 已設定好格式與合併欄位的 Word 檔 string output = @"d:\Final"; // 輸出之資料夾 object oMissing = System.Reflection.Missing.Va...

VLC c# 順利編譯

原文網址: http://www.cnblogs.com/haibindev/archive/2011/12/21/2296173.html 原文作者: haibindev 原文標題:c#万能视频播放器 本文的重點在於修正 class VlcPlayer,使其能順利在 VC# Express 2010 .Net Framework 4 下順利編譯。 修正重點在於 CallingConvention = CallingConvention. StdCall 改成 CallingConvention = CallingConvention. Cdecl using System; using System.Runtime.InteropServices; using System.Security; using System.Text; namespace VlcDotNet { class VlcPlayer { private IntPtr libvlc_instance_; private IntPtr libvlc_media_player_; private double duration_; public VlcPlayer(string pluginPath) { string plugin_arg = "--plugin-path=" + pluginPath; string[] arguments = { "-I", "dummy", "--ignore-config", "--no-video-title", plugin_arg }; libvlc_instance_ = LibVlcAPI.libvlc_new(arguments); libvlc_media_player_ = LibVlcAPI.libvlc_media_player_new(libvlc_instance_); } public ...

[Symfony+Doctrine] 透過非 Id 來使用 Pessimistic Lock

根據 文件 ,Doctrine 有 Pessimistic Lock,又分為兩種: LockMode::PESSIMISTIC_WRITE:對應至 MySQL 的 Select FOR UPDATE LockMode::PESSIMISTIC_READ:對應至 MySQL 的 Select LOCK IN SHARE MODE 差別在於 LOCK IN SHARE MODE 會將在 row 的資料鎖定(row-level lock),在非同一交易(Transaction)下,不給寫入,其他交易可以讀取, 且可以繼續 Select LOCK IN SHARE MODE 。而 FOR UPDATE 不僅鎖定該資料,在非同一交易下,不給寫入,其它交易可以讀取, 但不能 Select LOCK IN SHARE MODE 。MySQL 文件有更詳細的比較與情境使用的說明,參考 網址 。 現在問題是,我們要完全採用 ORM 來處理資料。Doctrine 的文件提到 EntityManager::find 可以採用 Pessimistic Lock, 但 find 是透過 id 來處理 。而其他 find 系列函數(包括:findAll, findBy, findOneBy)皆不支援 LockMode。 因此,勢必要有方法來「透過非 id 來使用 Pessimistic Lock」。透過查看原始碼,簡單的方法是有的,解法之範例如下: 19 public function depositAction() 20 { 21 22 $em = $this->getDoctrine()->getManager(); 23 24 $em->transactional(function ($em) { 25 $entityName = 'AcmeTrainingBundle:Account'; 26 $lockMode = LockMode::PESSIMISTIC_READ; 27 $orderBy = null; 28 $...