��̳������ɬ�ܤΡ֥ե����롦���å��󥰡�

��̳������ɬ�ܤǡ������⡢�ޤȤޤä�����ξ��ʤ��� UNIX �����ƥ�Υե��� �롦���å��󥰤ˤĤ��ơ����θ����ȼ�ˡ����⤷�ޤ������β���ϡ���������� ���٤Ƥ򥫥С�����櫓�ǤϤ���ޤ��󤬡����¤�ȯ�����뤹�٤Ƥ�������н褹 �뤳�Ȥ��Ǥ��ޤ���

creat(), link(), open() ���Υ����ƥࡦ������ˤĤ��Ƥϡ� UNIX �ץ������ �󥰡��ޥ˥奢��Σ��Ϥ�ʻ�ɤ���Ȥ狼��ޤ���POSIX 1003.1 �Υ��å������� �Ĥ��Ƥϡ����ʽ�����ǤϤ狼��ˤ����Ȼפ��ޤ��Τǡ��ܽҤ��ޤ�����

�ե����롦���å��󥰤�ɬ����

��UNIX�פϡ��ޥ�����桼�����ޥ������������ OS �Ǥ����顢��Ȥ�ȡ�ʣ���� �桼�������Ϥ��ơ�Ʊ���Ż��򤹤���֤λ�̳������Ŭ���Ƥ���櫓�Ǥ�����UNIX �����δ��פȤʤä���
   ��Ӥ����ƥ����ȥե�����κ��Ѥˤ�롢���ѥġ���μ¸�
   ���ޥ�ɤ�ľ�����ȥѥ��ץ饤��ˤ�롢̵�̤Τʤ�����ʸ����б�
   ����ɽ���ˤ�롢�ʷ�Ǹ�ΨŪ�ʥѥ�����ǧ��
�θ����ϡ�����ʬ����Ф������Ū�ʴĶ������߽Ф��ޤ���������ԥ塼����ʸ�� �䡢�������ξ���ˤϡ��ۤȤ�ɤǤƤ��ʤ�����Ǥ������ܼ�Ū���������ã���� �桼���δ֤Ǥϡ�����ԥ塼���Υ��ץꥱ�������Ȥ��Ƥϡ��㳰Ū��������Ǽ�� �Ƥ��ޤ���

���μ�Υ��ץꥱ����������ħ�ϡ���ץǡ�����߸˥ǡ�����ޤࡢ��Ʊ���ե� �����¿���Υ桼�������������Ȥ���פȤ������Ȥǡ��֥ե����롦���å��󥰡� (file locking)�����뤤�ϡ�����¾�����(mutual exclution) �ȸƤФ�뵻ˡ�� �Բķ�ˤʤ�ޤ���

�㤨�С����Τ褦�����ͤ��Ƥ���������

  1) ��ͤΥ桼�������߸˥ǡ����򹹿����뤿�ᡢ�߸ˤΥޥ����ե������
     �ǥ����������ɤ�ǡ��ǡ����򹹿������񤭴����롣
  2) �嵭�Υ桼�����ǥ������Υǡ�����񤭴��������ˡ�¾�Υ桼����Ʊ��
     �ǡ������ɤ�ǹ��������嵭�Υ桼�����ǥ�������񤭴�������ǡ���
     ʬ��ǥ�������񤭴����롣
����ǡ����Ȥ��ñ�ˡ��ǽ�Υ桼���Υǡ����ϡ������Ƥ��ޤ��ޤ��������Τ� ���ʾ����ΥХꥨ�������ϡ��������󤢤�ޤ���

���μ������ϡ� UNIX �Τ褦�� OS �Ρ������񸻤ζ�ͭ�פ��Ф��Ƥ�ȯ������ �Ť����鸦�椵��Ƥ��ޤ����������̤��ơ�������Ĥμ�ˡ������ޤ���

   �񸻤���ͭ����ǡ���󡦥ץ����� (daemon) ������
   �оݤȤ���񸻤���¾����μ»�
���Ԥϡ�������֥��饤����ȡ������С�����ǥ��(cleient-server model) �ȸƤФ���Τǡ� UNIX �������Ǥϡ������Υ��᡼�����顢�����С����ץ� �����Τ��Ȥ�֥ǡ�����(daemon) �ȸƤ�Ǥ��ޤ����㤨�С��߸˥ǡ����ι� ���ȾȲ���������˰���������ǡ����ʥ����С��ˤ�����Ư������¾�� �ץ������Ϥ��Υץ������ˡ���ͭ�ե�����ι����ȾȲ����ꤹ��Ȥ������� �ߤǤ����Ĥޤꡢ�����Ԥ��̤����Ȥˤ�ꡢ�ֶ��ѡפ��Τ�Τ��򤱤Ƥ��ޤ���ˡ �ǡ��ץ�����ߥ󥰤ϴ�ñ�ˤʤ�ޤ�������ν������Ʊ���ǡ��������оݤ������� �˽��äơ�����ץ�����ब�������������Ĥ��ʤ��ʤ�ޤ���

��Ԥ���ˡ�ϡ����٤ƤΥץ�����ब�����˻񸻤��Ѥ������ߤ���̷�⤬�Ǥʤ� �褦��ư�����Ȥ�����Τǡ������оݤ�¿�����ˤϡ����˸�Ψ���ɤ��ץ� ����ब���ޤ�������¾���椬ɬ�פˤʤꡢ���줬���β���Υơ��ޤǤ���

��¾����ϡ�������� (race condition) ���򤱤뤿��ˡ��������Ρֶ���פ� �����륯��ƥ�����(critical)�ʽ�����Ԥ��֡�¾�Υץ������ˤ��ե����롦 ����������ػߤ����Τǡ�����Ū�ˤϡ����Τ褦�ʥץ�����๽¤�ˤʤ�ޤ���

  lock();��������������/* ¾�Υץ������ˤ�롢�ե����롦����������ػ� */
  critical_secion(); ��/* �ǡ��������ʽ񴹡� */
  unlock();������������/* �ե��������ͭ���� */
lock() �ϡ���ʬ��������Υե�����ˡ�¾�Υץ����������������Ǥ��ʤ��褦�ˡ� �ֻܸ���(lock) ����Ȥ������᡼���Ǥ�������������ä��顢���򳰤��� (unlock)��¾�Υץ����������ƤӤ��Υե������Ȥ���褦�ˤ��ޤ���

���� lock()/unlock() ��¸�������ˡ�Ȥ��Ƥϡ���TSL (TEST AND SETLOCK)��̿ ���֥��ޥե� (semaphore)���������������ʤ�Τ��ͰƤ���Ƥ��ޤ����������� �Ǥϡ� UNIX �����Ѳ�ǽ�ǡ��ưפ��ĸ�ΨŪ�ʼ�ˡ�ˤĤ��ơ�������ߤ뤳�� �ˤ��ޤ���

UNIX ������Ū�ʼ�ˡ

������ lock()/unlock() ��¸����뤿��ˡ� UNIX �������ǡ��Ť�����Ȥ��� ������ˡ�ϡ����Τ褦�ʤ�Τǡ����٤ơ��֥ե������¸�ߡפ�����¾����Τ��� �Ρ֥ե饰 (flag)�פʤ����֥��ޥե���(���浡) �Ȥ��ƻȤ��ޤ���

creat() ������

���̥桼����������¸�ߤ��롢�񤭹��ߵ��ĤΤʤ��ե�������Ф��� creat() �� ���ƥࡦ�������¹Ԥ���ȥ��顼�ˤʤ뤳�Ȥ����Ѥ�����Τǡ��㤨�С����Τ� ���ʥ����ɤˤʤ�ޤ���


  #include <errno.h>

  lock(file) char *file;
  {
    extern int errno;
    int fd;

    while ((fd = creat(file, 0)) < 0) {
          if (errno != EACCES)
                  error("creat() error (%d)", errno);
          sleep(1);
    }
    return close(fd);
  }

  unlock(file) char *file;
  {
    return unlink(file);
  }

���Τ褦�ʥ����ǥ��󥰤ϡ��Τ� UNIX ���ޥ�ɤΤ��������˸����ޤ������� ��������Ȥ��Ȥ����������ϡ��֥����ѡ��桼�����Ф��Ƥϡ���¾���椬�����ʤ��� �Ȥ������ȤǤ�����ͳ�ϡ������ѡ��桼���ξ��ϡ��񤭹��߶ػߤ�̵���ˤʤ뤿 �ᡢcreat() �����顼�ˤʤ�ʤ����Ȥˤ���ޤ������Τ��ᡢ����������Ȥ���� �ϡ��ץ���������ˡ����ѼԤ������ѡ��桼�����ɤ���������å����뵡ǽ��ɬ �פˤʤ뤳�Ȥ�����ޤ���getuid(), geteuid() �Υ����ƥࡦ�����뤬��������Ū �ǻȤ��ޤ���

������ˡ�������ϡ����٤Ƥ� UNIX �ǻȤ��뤳�ȤǤ���access() �Υ����ƥࡦ ������ǡ��ե������¸�ߤ�����å����ơ�¸�ߤ��ʤ����ϡ���������Ȥ��� ��ˡ�Ǥϡ����ޤ��椫�ʤ����Ȥ����դ��Ƥ���������¸�ߤ��ʤ����Ȥ��ǧ���Ƥ� �顢��������ޤǤδ֤ˡ�¾�Υץ�������Ʊ��Ƚ�Ǥ򤷤ơ�Ʊ���ե�������ä� ���ޤ����Ȥ����뤫��Ǥ������Τ褦���񤷤����Τ�Τ�����¾�����ɬ�פȤ��� ����

link() ������

�嵭���ɤ������ͤ����ǡ�Ʊ��̾�Ρ֥�󥯡�(link) �ϰ�Ĥ������ʤ����Ȥ� ���Ѥ�����ΤǤ����㤨�С����Τ褦�ˤʤ�ޤ���


  #include <errno.h>

  lock(file) char *file;
  {
    extern int errno;
    int fd;
    char tmpfile[32];

    sprintf(tmpfile, "/tmp/LCK%d.tmp", getpid());
    if ((fd = creat(tmpfile, 0444)) < 0)
          error("can't creat %s", tmpfile);
    close(fd);

    while (link(tmpfile, file) < 0) {
          if (errno != EEXIST)
                  error("link() error (%d)", errno);
          sleep(1);
    }

    if (unlink(tmpfile) < 0)
          error("can't unlink %s", tmpfile);

    return 0;
  }

  unlock(file) char *file;
  {
    return unlink(file);
  }

������ˡ�ϡ������ޤ���ä������ΤǤ����������ѡ��桼�����Ф��Ƥ�Ȥ���Τ� �����Ǥ�������������󥯤��Τ�Τ���BSD-UNIX �Ǽ¸����줿�֥���ܥ�å��� ��󥯡�(symbolic link) ���̤ˤ���ȡ�Ʊ���ե����롦�����ƥ���Ǥ����Ȥ��� ���󤫤顢������������ޤ��󡣤��Τ��ᡢ�ܿ����Τʤ� BSD-UNIX ��ͭ�Υץ� ������񤯿ͤ˹��ޤ���ˡ�Ǥ���

open() ������

�Ƕ�� UNIX �Ǽ������줿�������� open() �� O_EXCL �ե饰�����Ѥ�����ˡ �ǡ�����¸�ߤ���ե�������Ф��� open(file, O_EXCL��O_CREAT, pmode) ���� �顼�ˤʤ�Ȥ�����ǽ�����Ѥ�����ΤǤ���O_EXCL �ե饰�ϡ��ҤȤĤΥץ����� �������������˥ե����������Ǥ��뤳�Ȥ��ݾڤ��ޤ���

�㤨�С����Τ褦�ˤʤ�ޤ���


  #include  <fcntl.h>
  #include  <errno.h>

  lock(file) char *file;
  {
    extern int errno;
    int fd;

    while ((fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0666))  < 0) {
          if (errno != EEXIST)
                  error("open() error (%d)", errno);
          sleep(1);
    }
    return close(fd);
  }

  unlock(file) char *file;
  {
    return unlink(file);
  }

�ǽ����Ĥ���ˡ������ˤʤä����桼���ȥե����륷���ƥ���Ф������¤Ϲ��� ����Ƥ��ޤ����������ƥ�θξ�䡢���å��ե�������ä��ץ��������������� ��ꡢ�֥ǥåɥ��å���(deadlock) �ˤʤä��ꡢ���˥����ƥ�򤿤��������Ȥ��� �ץ�����ब��Ư�Ǥ��ʤ��ʤä��ꤹ�뤳�Ȥ�����ޤ���

���Τ��ᡢ���å��ե������Ȥ��Ȥ��ϡ���/etc/rc�����ˡ������ƥ�ε�ư���ˡ� ���٤ƤΥ��å��ե������õ���³��������Ƥ����Τ����̤Ǥ���

������ˡ�ϡ��Ƕ�� UNIX �ΤۤȤ�ɤǻȤ��ޤ���

POSIX 1003.1 �μ�ˡ

UNIX �ο�����ɸ��Ǥ��롢��POSIX 1003.1�פǤ⡢���ޤǤ���ˡ���Ȥ���Τ��� ���Ǥ�����fcntl() �ˤ�뿷������¾���椬�Ȥ���褦�ˤʤ�ޤ������㤨�С��� �Τ褦�ˤʤ�ޤ���


  #include  <sys/types.h>
  #include  <fcntl.h>
  #include  <stdlib.h>

  lock(fd)
  {
    extern int errno;
    struct flock lock;

    lock.l_type = F_WRLCK;
    lock.l_whence = SEEK_SET;
    lock.l_start = (off_t) 0;
    lock.l_len = (off_t) 0;
    if (fcntl(fd, F_SETLKW, &lock)  < 0)
          error("fcntl(): F_SETLKW failed (%d)", errno);
    return 0;
  }

  unlock(fd)
  {
    extern int errno;
    struct flock lock;

    lock.l_type = F_UNLCK;
    lock.l_whence = SEEK_SET;
    lock.l_start = (off_t) 0;
    lock.l_len = (off_t) 0;
    if (fcntl(fd, F_SETLKW, &lock)  < 0)
          error("fcntl(): F_SETLKW failed (%d)", errno);
    return 0;
  }

������ˡ�ϡ�;ʬ�ʥե������ɬ�פȤ��ޤ��󤫤顢�ȤƤ⤹�ä��ꤷ�ޤ����ʲ��� ���� POSIX 1003.1 �Υե����롦���å��󥰤ˤĤ��ơ��⤦�����ܤ������⤷�ޤ���

�ޤ���struct flock �Υ��ФΤ�����l_type �˻���Ǥ���Τϡ����� 3�ĤΤ� ���줫�Ǥ���

  F_RDLCK �꡼�ɥ��å� read lock (���������ɥ��å� shared lock)
  F_WRLCK �饤�ȥ��å� write lock (��¾���å� exclusive lock)
  F_UNLCK ������å� (�嵭�դ��ĤΥ��å�����)

F_WRLCK �ϡ��ե������������ΰ�򡢤ҤȤĤΥץ��������������å��Ǥ���褦 �ˤ��뤿��Τ�Τǡ�����ϡ���¾���椽�Τ�ΤǤ����顢����¾���å��� (exclusive lock) �ȸƤФ�뤳�Ȥ�����ޤ��������� creat(), link(), open() ��Ȥä���������٤ơ��ե�����ι�����ɬ�פʰ���ʬ��������å����뤳�Ȥ��� ���ޤ����顢�����ξ�꤬�㤦�¤ꡢʣ���Υץ�������Ʊ���ˡ�Ʊ���ե�����˥� ���������뤳�Ȥ���ǽ�ǡ��ǡ��������θ�Ψ���ɤ��ʤ�ޤ���F_WRLCK �ϡ��о� �Ȥ���ե�����ˡ��񤭹��ߤΤ���Υѡ��ߥ�����ɬ�פȤ��ޤ���

F_RDLCK �����ϡ��̾�ե�������ɤ߼��˻��Ѥ��졢�ե�����ι�����ػߤ� �뤿��˻��Ѥ��ޤ������ξ��ϡ�����¾�Υץ������� F_RDLCK ������ʬ�ˡ��� ���С���åפ��� F_RDLCK �򤫤��뤳�Ȥ��Ǥ��ޤ����������F_WRLCK ���줿 ��ʬ�� F_RDLCK ��񤱤뤳�ȤϤǤ��ޤ��󡣤ޤ���F_RDLCK ���줿��ʬ�ˡ� F_WRLCK�򤫤��뤳�Ȥ�Ǥ��ޤ��󡣤Ĥޤꡢ�񤭹��ߤΤ���Υ��å��Ȱ�äơ� �ե�����Υ��å����줿��ʬ��ʣ���Υץ����������ɤ߹��ߤΤ���˶�ͭ���뤳�� ���Ǥ��뤿�ᡢ�֥��������ɥ��å���(shared lock) �ȸƤФ�뤳�Ȥ�����ޤ��� ������󡢤����Ȥ�����ˤϡ��꡼�ɤΥѡ��ߥ����ɬ�פǤ���

F_UNLCK �ϡ�F_RDLCK �� F_WRLOCK �ˤ����å��β���˻Ȥ��ޤ������������ �ϡ�<fcntl.h> ���������ޤ���

�ե�����Υ��å��ϰϤϡ�l_whence �� l_start, l_len �ǻ��ꤷ�ޤ����� l_whence �����θ����ǡ�l_start �����å���֤���Ƭ��l_len ��Ĺ���ˤʤ�ޤ���

l_whence �ϡ�lseek() ��Ʊ��ȯ�ۤǡ����� 3 �ĤΤ����줫����ꤷ�ޤ���

  SEEK_SET �ե�����λϤᤫ��
  SEEK_CUR �ե�����θ��߰��֤���
  SEEK_END �ե�����ν���꤫��

l_start �� l_len �����줾�졢������������������å���֤���Ƭ�ȡ�Ĺ���ˤ� ��ޤ������������Х��ȿ��� off_t (���̤� long) ���ǻ��ꤷ�ޤ���l_len �� 0 �ˤ���ȡ��ե����������֤����å����оݤˤʤ�ޤ����ޤ������å���֤ϡ� ���ߤΥե�����ν�����ۤ��ơ���äȸ�����ޤǻ��ꤹ�뤳�Ȥ��Ǥ��ޤ���

struct lock ��������Ȥ��� fcntl() �Υե����롦���å����ѥ��ޥ�ɤˤϡ� ���� 3 �Ĥ�����ޤ���

  F_GETLK  ��¸�Υ��å����֤�Ĵ�٤�
  F_SETLK  ���å���»�
  F_SETLKW ���å�����������ޤ��Ԥ�

�ޤ���l_type, l_whence, l_start, l_len �ˡ���ʬ��ɬ�פȤ��������ȶ�֤� �åȤ��ơ�F_GETLK ���ޥ�ɤ� fcntl() ��¹Ԥ���ȡ����Τ����줫�η�̤��� ���ޤ���

   �����֤����å���ǽ�ʤ顢l_type �� F_UNLCK �����åȤ��졢
       ����¾�Υ��Фϡ��Ѥ��ޤ���
   �����֤���¸�Υ��å��ˤ�������ϡ�l_whence, l_start, l_len
       �˴�¸�Υ��å���֤����åȤ��졢���å���»ܤ����ץ�����
       ID �� l_pid �˥��åȤ���ޤ���
struct flock �Υ��ФǤ��� l_pid �ϡ�����ʳ������ӤˤϻȤ��ޤ���

F_GETLK �����դ��٤����ϡ����Υ��ޥ�ɤǡ����å�����Ƥ��ʤ����Ȥ��ǧ���� �Ȥ��Ƥ⡢�ºݤ˥�����������Ȥ��ޤǤˡ�¾�Υץ������ˤ�äƥ��å������� ǽ��������Ȥ������ȤǤ����ĤޤꡢF_UNLCK �ˤʤä��Ȥ��äƤ⡢�¿��Ǥ��� ���������ˡ����å�����Ƥ��ʤ����ɤ����γ�ǧ�ϡ���ʬ�����å����Ƥ��ޤ��� ���ˤʤ��ΤǤ���

F_SETLK �� F_SETLKW �ϡ����˥ե�����˥��å��򤫤��륳�ޥ�ɤǤ��������Ԥϡ� ����¾�Υץ������ˤ����å�����Ƥ��뤿�ᡢ���å��򤫤���Τ˼��Ԥ������ �ϡ�errno �� EACCES �� EAGAIN (������ˤʤ뤫�ϡ������ƥ��¸) �򥻥åȤ� ����뤳�ȤˤʤäƤ��ޤ��Τǡ����å��Ǥ��ʤ����ϡ�¾�λŻ��򤹤�褦�ʹ� ¤�Υץ������ǻȤ��ޤ��������������ͤ������ʤ�õ���񤷤�������ޤ���

F_SETLKW �����ϡ����å����������뤫��signal �ˤ������ߤ�������ޤ��Ԥ� �ޤ����顢���Υᥫ�˥������Ǥϡ��Ǥ�Ȥ��䤹�����ޥ�ɤǤ����ǥåɥ��å� ����β����䡢�۾��Ĺ�������Ԥ����줿�Ȥ����к��ˡ�alarm() ���Ȥ߹�碌�� �Ȥ����Ȥ⤢��ޤ��������ʥ�����Ǥ��줿���ϡ�¾�Υ����ƥॳ�����Ʊ�ͤˡ� EINTER �� errno �����ѿ��˥��åȤ��ơ�-1 �����ޤ���

F_SETLK, F_SETLKW �ˤ����å��ϡ��оݤȤʤ�ե����뤬 close() ���줿��硢 ��ưŪ�˲������ޤ��Τǡ�creat(), link(), open() �ˤ����å������Τ褦�ˡ� ���å��ե����뤬�Ĥ����������ޤ���

�ե����롦���å�������

���ޤǽҤ٤������٤ƤΥ��å������ϡ���Ū�Υե�������Ф��륢���������Τ�� ��ػߤ���櫓�ǤϤ���ޤ���ñ�ˡ��֤��Υե�����ϥ��å�����Ƥ��ޤ���� �Ȥ������Ȥ�OS �������Ƥ��������ǡ��桼���ץ������ϡ����Ρִ���פ�̵ �뤷�ơ��ɤ߹��ߤ�񤭹��ߤ򶯹Ԥ��뤳�Ȥ��Ǥ��ޤ���

�㤨�С��嵭��������ư���ֺ߸˴����ץ������פ��ޥ����ե�����򹹿��� �Ƥ���Ȥ����ե����롦���å��󥰤ʤɵ��ˤ⤫���ʤ��֥��ǥ����פǡ��ޥ����� ��������ѹ�����Ȥ��ä����֤��ɤ����ȤϤǤ��ʤ��ΤǤ���

���Τ��ᡢ���������Υ��å������ϡ�advisory file locking��(���������λܸ�) �ȸƤФ�ޤ���

������Ф��ơ��оݤȤ���ե����뤽�Τ�Τ˻ܸ������������Mandatory locking��(�ܼ�Ū�ܸ�) �ȸƤӡ�����������¸����������ƥ�⤢��ޤ����� ��POSIX 1003.1�פǤϡ������Ĥ��������Ѥ��ǰ���ơ����Ѥ��ޤ���Ǥ��������� �����Υ��å��ϡ��ֶ����⡼�ɡ�(enforcement-mode) �Υ��å��ȸƤФ�뤳�Ȥ� ����ޤ���

�������å���ɬ�פȤ��뤳�Ȥϡ���ä��ˤ���ޤ��󤬡��ɤ����Ƥ�Ȥ������ϡ� chmod() �����ƥࡦ�������ʻ�Ѥ��ơ��¸����뤳�Ȥ��Ǥ��ޤ���

�ǥåɥ��å�

��¾����ˤĤ��ޤȤ�����ΤҤȤĤˡ֥ǥåɥ��å���(deadlock) ������ޤ��� ����ϡ��ץ���������ư���Ĥ��ʤ��ʤ���֤ǡ��㤨�С����Υ�������ͤ��Ƥߤ� ����������

  �ǽ�Υץ���������ñ���ե��������å��������ˡ�ȯ����
      �ե��������å����褦�Ȥ��롣
  �̤Υץ����������嵭�Υץ�������ȯ����ե��������å�
      �������ˡ�ȯ����ե�����Υ��å���������������ñ��
      �ե��������å����褦�Ȥ��롣
����ǡ�������ĤΥץ������ϡ��ˤä��⤵�ä���椫�ʤ��ʤ�ޤ���

���β��ˤϡ������Ĥ�����ˡ������ޤ������㤨�С�

  �ե��������å�������֤���롣
  ʣ���Υե��������å�������ϡ�����ܰʹߤΥ��å��˼��Ԥ�������
      ����ޤǤΥ��å��������롣
�Ȥ��ä���ˡ�����褯�Ȥ��ޤ���ʣ���Υ��å���ʻ�Ѥ�����ϡ����դ�ɬ�פ� ����

�����ʥ�ν���

�ե����롦���å��󥰤�Ԥ����Ȥ���Ȥ������å�����λ�����������뤤�ϡ����� �������������ˡ�ü������γ����ߤ�����Ȥ����ץ������� kill �����Ȥ� �ä���礬����ޤ���

����ˤʤ�Τϡ������ʥ�ˤ�äƥץ���������ߤ����Ȥ������å��ե����뤬�� �äƤ��ޤ��������ǡ����å����ե������Ȥ����ϡ����Τ褦�ʡ֥��꡼�󡦥� �åס�(clean up) �����Υץ�����������Ƥ����Τ����̤Ǥ���


  #include  <signal.h>

  void onint();
  char *lock_file;        /* ���å��ե�����̾ */

  ..
  signal(SIGINT, onint);  /* ü������γ����� */
  signal(SIGHUP, onint);  /* ��ǥ�β����� */
  signal(SIGTERM, onint); /* kill() �ˤ�äƻ����줿�Ȥ� */
  ..

  void onint(sig)
  {
    unlink(lock_file);
            exit(0);
  }

�ʾ�ǡ��ե����롦���å��󥰤���ɽŪ�ʼ�ˡ������������⤷�ޤ����Τǡ��ʲ��� ���α�����ˤĤ��ƽҤ٤ޤ���

��Ϣ�ֹ�����ץ������

��ʸ���Ǽ�ʽ񡢸��ѽ�Τ褦�ˡ��ȿ��Ȥ��ơ���ˡ����ʰ�Ϣ�ֹ���������Ȥ� �����ϡ������ƥ�Τɤ����ˡ������ֹ�򵭲������ե������ݻ�����ɬ�פ��� ��ޤ��������ξ��⡢��¾���椬ɬ�פǤ���

POSIX 1003.1 �Υե����롦���å������Ѥ����ץ������ΰ���ϡ����Τ褦�ˤʤ� �ޤ�������������Ȱ�äơ�;ʬ�ʥե������ɬ�פȤ��ʤ����ȤƤ⥷��ץ�ʹ� ¤�ˤʤäƤ��뤳�Ȥˡ����դ��Ƥ��������� MINIX ���ٶ���������ϡ�1.6 �ʹ� �ΥС������ɬ�פˤʤ�ޤ����Ť� UNIX �ξ��ϡ�lock()/unlock() ���� �˽Ҥ٤���ˡ���ѹ�����ɬ�פ�����ޤ���

¿���ξ�硢������� seqno() �ؿ�����������ʸ���ȯ������¾�Υץ������� �������Ȥ߹��ޤ�ƻȤ��뤳�Ȥˤʤ�ޤ��������Τ褦����Ω�����ץ������ϡ� ��sh ������ץȡפǻȤ���Τ������ǡ�����Υ桼������ñ�����ѤǤ������ǡ� �礤����Ω�Ĥ��Ȥ�����ޤ���

�ޤ��������Ǥϡ���̳�ѤΡ֥ʥ�С�����󥰡פΤ褦�ˡ�ñ�˰�Ĥο��ͤ򵭲� ����ե����뤬�Ȥ��Ƥ��ޤ������֥����פȡְ�Ϣ�ֹ�פ򥻥åȤǻȤ����Ȥ� ��ꡢȯ������������������ʣ���δ����оݤμ����ֹ���ĤΥե����������� �������Ȥ��ǽ�Ǥ���

POSIX �Υե����롦���å��󥰤��Ȥ��ʤ����ϡ�lock(), unlock() �������� ¾����ˡ�Τ����줫���ѹ����ޤ���


  /*
   * seqno - get a unique sequential number
   */
  #include  <sys/types.h>
  #include  <fcntl.h>
  #include  <stdio.h>
  #include  <errno.h>
  #include  <unistd.h>

  #define SEQFILE "/usr/etc/SEQNO"  /* file to store sequential-No. */

  char buf[BUFSIZ];

  main(argc, argv) char **argv;
  {
    int n;

    if ((n = seqno()) == -1)
          return 1;
    printf("%d\n", n);
    return 0;
  }

  seqno()
  {
    int fd, i, j, n;
    char buf[32];
    extern errno;

    if ((fd = open(SEQFILE, O_RDWR | O_CREAT, 0664)) == -1)
          return -1;
    lock(fd);
    if ((i = read(fd, buf, sizeof(buf))) == -1)
          return -1;
    else if (i == 0)
          sprintf(buf, "0\n");    /* just created */

    n = atoi(buf);
    sprintf(buf, "%d\n", n+1);    /* next available number */
    j = strlen(buf);
    lseek(fd, 0L, SEEK_SET);      /* rewind */
    if ((i = write(fd, buf, j)) != j)
          return -1;
    unlock(fd);
    close(fd);
    return n;
  }

  lock(fd)
  {
    struct flock lock;

    lock.l_type = F_WRLCK;
    lock.l_whence = SEEK_SET;
    lock.l_start = (off_t) 0;
    lock.l_len = (off_t) 1;
    if (fcntl(fd, F_SETLKW, &lock)  < 0) {
          fprintf(stderr, "lock(): F_SETLKW failed\n");
          return -1;
    }
    return 0;
  }

  unlock(fd)
  {
    struct flock lock;

    lock.l_type = F_UNLCK;
    lock.l_whence = SEEK_SET;
    lock.l_start = (off_t) 0;
    lock.l_len = (off_t) 1;
    if (fcntl(fd, F_SETLKW, &lock)  < 0) {
          fprintf(stderr, "unlock(): F_SETLKW failed\n");
          return -1;
    }
    return 0;
  }

���ޥ�ɤ���¾�¹�

�ե��������¾Ū���������ʳ��ˡ���ʬ���Ȥ�ޤ�ơ������Υ��ޥ�ɤ���¾Ū�� �¹Ԥ������Ȥ�������¿�����㤨�С����Υץ������ϡ���Ȥ����¾Ū�Ǥʤ� ���ޥ�ɤ���¾Ū�˼¹Ԥ����ޤ���

���Υץ������Ǥϡ��������ɥå����ʥ��å����ե������Ȥ������ˤʤäƤ��� �����顢�㤨�С�


  $ xr ls /usr/tmp

��¹Ԥ���ȡ����Υץ������μ¹����������/usr/tmp/ls.LCK�פȤ����ե����� ���Ǥ��Ƥ��뤳�Ȥ��ǧ���뤳�Ȥ��Ǥ��ޤ���

���Υץ������ϡ�open() ��Ȥä���¾�������Ѥ��Ƥ��ޤ����桼�������ꤷ �����ޥ�ɤ�¹Ԥ���ץ������ϡ������ʥ�ǻ�����ƤϺ���ޤ��Τǡ�fork() ��ʬΥ������ǡ������ʥ��̵�뤹��褦�ˤ��Ƥ��뤳�Ȥ����դ��Ƥ����������� �å����ե�����ˤϡ���/usr/tmp/���ޥ��̾.LCK�פȤ���̾����ȤäƤ��ޤ��� ���Τ��ᡢ�̤Υǥ��쥯�ȥ�ˤ���Ʊ̾�Υ��ޥ�ɤ�Ʊ���˼¹Ԥ��뤳�ȤϤǤ� �ޤ��󡣤⤷����򤷤������ϡ�which() ���������ơ����Хѥ�̾�Ǽ��̤���� �����ѹ����Ƥ������������δؿ��ϡ����ꤵ�줿���ޥ�ɤΡ����Хѥ�̾�פ��� �ޤ���


  /*
   * xr - run command exclusively
   */

  #include  <sys/types.h>
  #include  <fcntl.h>
  #include  <signal.h>
  #include  <stdlib.h>
  #include  <string.h>
  #include  <unistd.h>
  #include  <errno.h>
  #include  <stdio.h>

  void usage();
  void error();
  void onint();

  char *file;
  char lockfile[128];
  char *cmd;

  int main(argc, argv)  char **argv;
  {
    int pid, status, w;

    cmd = argv[0];
    if (argc  < 2)
          usage();

    file = argv[1];
    sprintf(lockfile, "/usr/tmp/%s.LCK", file);
    signal(SIGINT, onint);
    signal(SIGHUP, onint);
    signal(SIGTERM, onint);
    lock(lockfile);
    if ((pid = fork()) == 0) {
          signal(SIGINT, SIG_DFL);
          signal(SIGHUP, SIG_DFL);
          signal(SIGTERM, SIG_DFL);
          execvp(file, ++argv);
          error("can't exec %s", file);
    }
    while ((w = wait(&status)) != pid && w != -1)
          ;
    if (w == -1)
          status = 1;
    unlock(lockfile);
    return status;
  }

  void onint()
  {
    unlock(lockfile);
    exit(1);
  }

  void usage()
  {
    fprintf(stderr, "Usage: %s command [arg ..]\n", cmd);
    exit(1);
  }

  void error(s, t) char *s, *t;
  {
    fprintf(stderr, "%s: ", cmd);
    fprintf(stderr, s, t);
    fprintf(stderr, "\n");
    exit(1);
  }

  lock(file) char *file;
  {
    extern int errno;
    int fd;

    while ((fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0666))  < 0) {
          if (errno != EEXIST)
                  error("open() error (%d)", errno);
          sleep(1);
    }
    return close(fd);
  }

  unlock(file) char *file;
  {
    return unlink(file);
  }

  #if 0
  char *which(cmd) char *cmd;
  {
    static char pathnam[512];
    char *path, *s, *t, *getenv();

    if (strchr(cmd, '/') != NULL) {
          strcpy(pathnam, cmd);
          if (access(pathnam, 1) == 0)
                  return pathnam;
    }
    else {
          if ((path = getenv("PATH")) == NULL)
                  path = ".:/bin:/usr/bin";
          for (s = path; *s; ) {
                  for (t = pathnam; *s && *s != ':'; )
                          *t++ = *s++;
                  *t++ = '/';
                  strcpy(t, cmd);
                  if (*s == ':')
                          s++;
                  if (access(pathnam, 1) == 0)
                          return pathnam;
            }
    }
    return (char *)0;
  }
  #endif

��¾����μ¸�

�Ǹ�ˡ���¾����θ��̤�´����뤿��μ¸��򤷤Ƥߤޤ��礦��[6] �ΰ�Ϣ�ֹ� ����ץ������˾����ٹ��򤷤ơ���¾����򤷤ʤ��褦�ˤ��뤿��Υ��ץ��� ���-d�פ��ɲä���Ʊ���ˡ����ͤ������פ��褦�ˡ�DELAY() ���������ơ�ư��� �٤����ޤ���

�㤨�С�


  $ sn & sn

��¹Ԥ���ȡ����Τ褦�ˤʤäơ�
    0, pid(189)
    1, pid(189)
    3, pid(189)
    2, pid(188)
    5, pid(188)
    4, pid(189)
    7, pid(189)
    6, pid(188)
    8, pid(189)
   10, pid(189)
    9, pid(188)
   12, pid(188)
   11, pid(189)
   14, pid(189)
   13, pid(188)
   15, pid(189)
   16, pid(188)
   17, pid(188)
   18, pid(188)
   19, pid(188)
��¾����η�̡�ʣ���Υץ������������줾���ʣ���ʤ�����Ϣ�ֹ��������� ���Ȥ��Ǥ��ޤ�������¾�����ػߤ��ơ�

  $ sn -d & sn -d

��¹Ԥ���ȡ��㤨�С����Τ褦�ˤʤäơ�
    20, pid(180)
    20, pid(181)
    21, pid(181)
    21, pid(180)
    22, pid(181)
    22, pid(180)
    23, pid(180)
    23, pid(181)
    24, pid(181)
    24, pid(180)
    25, pid(181)
    26, pid(181)
    25, pid(180)
    26, pid(180)
    27, pid(181)
    27, pid(180)
    28, pid(180)
    28, pid(181)
    29, pid(181)
    29, pid(180)
����줿�ֹ椬��ʣ���Ƥ��ޤ��ޤ���

�¸��ѥץ������ϡ����ΤȤ���Ǥ�����POSIX �Υ��å��󥰵������Ȥ��ʤ���� �ϡ������Τ����줫����ˡ�˽񤭴����Ƥ����������ޤ����ե��åԡ����ǥ������� ��ε�ư�Τ褦�ˡ��ץ������ε�ư�˻��֤���������ϡ�DELAY() �λ��֤�Ĺ ��������������ʬ�Υ����ƥ�˹�碌�ơ�Ĵ�����Ƥ���������


  /*
   * sn - get a unique sequential number
   */

  #include  <sys/types.h>
  #include  <fcntl.h>
  #include  <stdio.h>
  #include  <errno.h>
  #include  <unistd.h>

  #define SEQFILE         "SEQNO"

  int dflg;       /* disale mutual exclution */

  main(argc, argv) char **argv;
  {
    char *s;
    int i, n, pid;

    while (--argc > 0 && (*++argv)[0] == '-')
          for (s = argv[0]+1; *s; s++)
                  switch(*s) {
                  case 'd':
                          dflg++;
                          break;
                  }
    pid = getpid();
    for (i = 0; i  < 10; i++) {
          n = seqno();
          printf("%d, pid(%d)\n", n, pid);
    }
    exit(0);
  }

  seqno()
  {
    int fd, i, j, n;
    char buf[32];
    extern errno;

    if ((fd = open(SEQFILE, O_RDWR | O_CREAT, 0664)) == -1)
          return -1;
    if (!dflg)
          lock(fd);
    if ((i = read(fd, buf, sizeof(buf))) == -1)
          return -1;
    else if (i == 0)
          sprintf(buf, "0\n");    /* just created */

    DELAY();
    n = atoi(buf);
    sprintf(buf, "%d\n", n+1);    /* next available number */
    j = strlen(buf);
    lseek(fd, 0L, SEEK_SET);      /* rewind */
    if ((i = write(fd, buf, j)) != j)
          return -1;
    if (duflg)
          unlock(fd);
    close(fd);
    return n;
  }

  DELAY()
  {
    int i, j;

    for (i = 0; i  < 10000; i++)
          for (j = 0; j  < 10; j++)
                  ;
  }

  lock(fd)
  {
    struct flock lock;

    lock.l_type = F_WRLCK;
    lock.l_whence = SEEK_SET;
    lock.l_start = (off_t) 0;
    lock.l_len = (off_t) 1;
    if (fcntl(fd, F_SETLKW, &lock)  < 0) {
          fprintf(stderr, "lock(): F_SETLKW failed\n");
          return -1;
    }
    return 0;
  }

  unlock(fd)
  {
    struct flock lock;

    lock.l_type = F_UNLCK;
    lock.l_whence = SEEK_SET;
    lock.l_start = (off_t) 0;
    lock.l_len = (off_t) 1;
    if (fcntl(fd, F_SETLKW, &lock)  < 0) {
          fprintf(stderr, "unlock(): F_SETLKW failed\n");
          return -1;
    }
    return 0;
  }

�ͥåȥ����ͭ������

�ʾ塢��¾������Ȥˤ�����������֤��н�ˡ��Ҥ٤Ƥ��ޤ��������������٤� �ե����뤬¾�Υޥ���˱�����Ƥ��롢�ͥåȥ���ξ��ϡ����饤����ȡ��� ���С�����ǥ�����Ѥ���Τ�����ñ�Ǥ���

���ξ��ϡ������С�¦�ǡ��ȥ�󥶥������ (transaction) �ȸƤФ�롢�Բ�ʬ �Ρָ���ư���(atomic action) ���Ѱդ������饤����Ȥ��ȥ�󥶥������γ� �Ϥ��齪λ���������ޤǤδ֡�¾�Υ��饤����ȤؤΥ����ӥ��򤷤ʤ��褦�ˤ� ��Τ����̤Ǥ����ȥ�󥶥����������Ǥ�����ϡ���Ȥξ��֤��ᤷ�ޤ���

����ư��Ȥ����Τϡ�¾�Υץ������ˤ�ä����Ǥ��줺�˼¹Ԥ���롢ư��κǾ� ñ�̤Ȥ�����̣�Ǥ���������ʾ�ʬ��Ǥ��ʤ��Ȥ�����̣�ˡ��ָ��ҡ�(atom)��� ���Τϡ����ʤ��Τ�ȯ�ۤǡ�����ԥ塼���ؼԤϡ�ʪ���ؤʤ��ٶ����ʤ�����˺�� �Ƥ��ޤä��Ȥ������ȤǤ��礦����

�ޤ����ͥåȥ����ͭ�Ρ����򤯤Ƽ���Ū������ˡ���Դ֤λ���ư�η������ ¿���Υ����ƥ��ʬ������ե����빹��������ޤ��������ξ��ϡ�CCR (commitment concurrency, and recovery) �ȸƤФ���ˡ��Ȥ��Τ����̤ǡ����� �ϡ�two-phase commit�פȸƤФ�뵻ˡ���ˤ��Ƥ��ޤ�������Ū�ˤϡ��㤨�С� ����򴹤ξ�硢���Τ褦�ˤʤ�ޤ���

  ����򴹽�ϡ����ΰ�����Ȥ���Ԥ�������ζ�Ԥˡ���ۡ����
      �����ξ���򤷤餻�롣

  �Τ餻������������ƥ�ϡ������׵᤬�¹Բ�ǽ�ʾ�硢�����׵��
      ��������ȶ��ˡ��оݤȤʤ�ǡ�������å����������α�����
      �֤���¾�Ԥμ��Ԥ������ơ�������֤⵭�����롣�¶���­��
      ���¤��ʤ�������ͳ�ǡ����ޤ��椫�ʤ��Ȥ��ϡ����Ԥα�����
      �֤���

  ����򴹽�ϡ����٤Ƥζ�Ԥ��������α�������ä��顢�֥��ߥåȡ�
      (commit - ����) ��å����������äơ�������¹Ԥ����롣����
      �줫�ζ�Ԥ����Ԥ������䥯��å���򸡽Ф������ϡ����
      ���֤ؤ������ȥ��å��β����ؼ����롣

���ͽ�

�����Ȥ��Ƥ���¾����ˤĤ��Ƥϡ�����������ʸ��������ޤ�������MINIX �ΥХ� �֥�פȸƤФ�Ƥ��� OS �β����

   Andrew S. Tanenbaum,- Operating System: Design and Impementation
   (Prentice-Hall, USA) ISBN: 0-13-637331-3
�� 2.2 ���� 2.3 �β���Ȼ���ʸ���Υꥹ�Ȥ����ɤ��Ǥ��Ƥ���Ȼפ��ޤ����� ���ϡ�
   ����������,- �ͣɣΣɣإ��ڥ졼�ƥ��󥰡������ƥ�
   (������������) ISBN: 4-7561-0000-7
�Ǥ�����¿�����������˱̤줺�����ʤ�θ���������ޤ����顢��������ǽ��ʬ �ϸ����פȤ���Ƭ�ǤĤ��礦ɬ�פ�����ޤ����������������Ҥɤ�����Ȥ�פ��� ���� MINIX �θ��ߤ��Ǥ��鸫��ȡ������Ť��ʤäƤ��ޤ�����2.0 ���������� �����ǡ��񤭴�������ͽ��Ǥ���¿ʬ��POSIX ��Ϣ�ε��Ҥ�����Ȼפ��ޤ����� �����������ΤޤޤǤ⡢OS �� UNIX ���̤β���Ȥ��Ƥϡ�������Ť��ʤ��Ǥ����� ���ɤ��ܤǤ���

�嵭���顢 MINIX ��ͭ����ʬ������ơ������̲��������ǽ񤫤줿�Τ���

   Andrew S. Tanenbaum,- Modern Operating Systems
    (Prentice-Hall, USA) ISBN: 0-13-595752-4
�Ǥ���USENET �Υ˥塼�����롼�פǤ����\tt{comp.os.minix} \rm�פǡ�MS-DOS �Τ��ȤϤޤ�Ǥ狼��ʤ������Ѥ��������Ȥ�פ�ʤ��פʤ�ƽ񤤤Ƥ������Ԥ��� MS-DOS �������ʲ����񤤤Ƥ���Ȥ����������ܤǤ������Ȥˤ������褯�Ǥ� �Ƥ��ޤ��������ϡ�
  ���Ͽ�Ƿ���������û���,- �ϣӤδ��äȱ���
  (�ץ��ƥ����ۡ���) ISBN4-8101-8543-5
�Ǥ���ʬ�������ƥ�ε��Ҥ��ɲä���ޤ�����

�ޤ����ͥåȥ��������ˤĤ��Ƥϡ�Ʊ�����ԤΡ�

   Andrew S. Tanenbaum,- Computer Networks
    (Prentice-Hall, USA) ISBN: 0-13-166836-6)
�����ɤ��ɤޤ�Ƥ��ޤ��������ϡ��ʲ����̤�Ǥ���
   ��ƣ¾��,- ����ԥ塼���ͥåȥ��
     (����) ISBN: 4-621-03699-8
ʿ�� ����, 1993