Concurrent with Semaphore

Semaphore

Dijkstra 大佬提出了一种解决不同线程之前同步和互斥问题的方法。这种方法就是 PV 操作,它基于 Semaphore(信号量)。

可以把信号量简单看成一个非负整数,只能使用两种操作来改变它的值,这两种操作就是 P 和 V,用伪代码描述如下(与教材《操作系统教程》上不同,这里的信号量不能为负值)。PV 操作的伪代码实现如下:

  • P(s)

    P(s) {
        if (p != 0) {
        	s--;
        } else {
        	append this thread to list;
        	sleep();
        }
    }
    
  • V(s)

    V(s) {
        s++;
        if (list is no empty) {
            list.pop().wakeup();
        }
    }
    

P 和 V 的执行过程都是不可打断的,并且 P 和 V 要成对的出现。这样就保证了程序不可能进入信号量为负值的状态,可以利用这个特性实现进程之间的互斥和同步。

阅读全文

6.828 Homework 2:Shell

这次的作业是实现一个简单的 shell。通过阅读 xv6 book 的第零章,基本上就可以实现题目中所说的三个功能,也是shell的基本功能:运行简单的命令,输入输出重定向,管道。

题目提供的sh.c已经实现了命令的解析(大概看了一下流程,大概就是个递归下降解释器吧,这次作业无需关心这个),只需要完成runcmd函数中缺少的代码即可。

流程

先从 main 函数看起:

int main(void) {
  static char buf[100];
  int fd, r;

  // Read and run input commands.
  while (getcmd(buf, sizeof(buf)) >= 0) {
    if (buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' ') {
      // Clumsy but will have to do for now.
      // Chdir has no effect on the parent if run in the child.
      buf[strlen(buf) - 1] = 0; // chop \n
      if (chdir(buf + 3) < 0)
        fprintf(stderr, "cannot cd %s\n", buf + 3);
      continue;
    }
    if (fork1() == 0)
      runcmd(parsecmd(buf));
    wait(&r);
  }
  exit(0);
}

main 函数循环调用 getcmd从 console 读取命令,对 cd 命令做了特别处理。之后fork创建子进程,调用parsecmd解析命令,再调用runcmd执行得到的命令。最后调用wait等待子进程结束。main 的基本流程就这样。

阅读全文

JavaFX与Kotlin的Main函数

晚上想做个小应用,不想用 丑陋的swing(确信)。于是试了试JavaFX。MVC 模式,XML 和 Scene Builder 设计 UI,设计出的 UI 颜值还高。这样一看还是比较熟悉的嘛,好像和 Android 的套路差不多。

当然还是要用Kotlin。不过在写Main函数的时候就遇到问题了,简直气炸(

三次尝试

首先,在 Java 里的代码应该是这样的:

public class Main extends Application {
    //...
    public static void main(String[] args) {
        launch(args);
    }
}

没有任何问题。

那么在 Kotlin 中,我首先想到的是 Top level 的 Main 函数:

fun main(args: Array<String>) = Application.launch(*args)

class Main : Application() {
	//...
}

阅读全文

Emoji in git commit

Text? Emoji? 今年早些时候,在 GitHub 上对某个开源项目贡献了一点代码。原作者(是小米的员工了)还帮着我 review code。过去几个月了还是记得很清楚。GitHub 是

阅读全文

「只差一个程序员」

跟人聊天,该人懂一点中文,外派几年管理江苏的一家企业,聊着聊着忽然说:“我发现在中国的日常生活里,人们喜欢彼此制造困难让大家日子难过(Die

阅读全文

C语言-可怕的指针

一重指针

简单使用

int a = 1;
int *p = &a; //defines an pointer to a, the address where a store.
printf("%d", a);
printf("%d", *p); //here * is poiner operator, get the value of address = a.

数组指针

  • 数组名代表数组的首地址,二维数组名则是行地址

  • 一维数组

     int a[4] = {1, 2, 3, 4};
     int *p1 = a;
     printf("%d", a[1]); //2
     printf("%d", (*++p1)); //2
    
  • 二维(多维)数组

     int b[2][4] = {{1, 2, 3 ,4},{5., 6, 7, 8}};
     int (*p2)[4] = b; //**A pointer** to a array of 4 integers,行地址
     int (*p3)[2][4] = &b; //**A pointer** to 2d array
     b[1][1];//5
     *((*p2 + 1) + 1); //5,(*p + 1) == 一维数组b[1]的首地址
     p2[1][1]; //5
     (*p2)[1][1]; //5
    
    

阅读全文