10月 31
  1.  --------------------------线程的创建---------------------------
  2.  
  3.  pthread_t mythread;
  4.  //线程句柄声明,用来存放tid
  5.  
  6.  pthread_create( &mythread, NULL, thread_function, NULL)
  7.  //创建新的线程
  8.  //参数一:线程句柄,存放tid
  9.  //参数二:线程函数返回值
  10.  //参数三:线程函数,由thread_function函数指针定义
  11.  //参数四:线程函数的参数
  12.  
  13.  pthread_join ( mythread, NULL )
  14.  //等待mythread线程于主线程合并
  15.  
  16.  fflush(stdout);
  17.  //清空标准输出缓冲区
  18.  
  19.  
  20.  
  21.  --------------------------线程的同步(互斥锁)---------------------------
  22.  pthread_mutex_t mymutex=PTHREAD_MUTEX_INITIALIZER;
  23.  //初始化mymutex互斥锁(使用宏的静态版本)
  24.  
  25.  
  26.  pthread_mutex_t mymutex;
  27.  pthread_mutex_init(&mymutex,NULL);
  28.  //初始化mymutex互斥锁(动态版本)
  29.  
  30.  pthread_mutex_lock(&mymutex);
  31.  //mymutex上锁,当得不到互斥锁时,进入等待队列,直到得到为止
  32.  
  33.  pthread_mutex_trylock(pthread_mutex_t *mutex)
  34.  //mymutex上锁,当得不到互斥锁时,立刻返回EBUSY
  35.  
  36.  pthread_mutex_unlock(&mymutex);
  37.  //mymutex解锁
  38.  
  39.  pthread_mutex_destroy(&mymutex)
  40.  //释放mymutex指针指向的资源(释放mymutex指针指向的内存,并不指针本身)
  41.  
  42.  
  43.  --------------------------线程的同步(等待)---------------------------
  44.  pthread_cond_t mycond;
  45.  //定义条件变量mycond
  46.  
  47.  pthread_cond_init(&mycond,NULL);
  48.  //初始化条件变量mycond
  49.  
  50.  pthread_cond_destroy(&mycond);
  51.  //释放mycond指针指向的资源
  52.  
  53.  pthread_cond_wait(&mycond, &mymutex){
  54.      mymutex解锁;
  55.      while(1){
  56.          mycond休眠并等待被唤醒;
  57.          if(mycond被唤醒)
  58.              if(mymutex上锁成功)
  59.                  return 0;
  60.      }
  61.  }
  62.  //等待mycond得到信号被唤醒
  63.  
  64.  pthread_cond_broadcast(&mycond);
  65.  //对mycond广播唤醒信号
  66.  
  67.  pthread_cond_signal(&mycond);
  68.  //对mycond单播唤醒信号(通常是下一个)
7月 04

昨天应聘的一道题目,将32bit容量的整型转成字符.编译通过,从函数参数方面比较,IntToString明显要好于inttostr,算法都是o(n)级别的

#include <stdio.h></stdio.h>
 
int inttostr(int i, char *s, int *p);
char* IntToString(int value, char* string);
 
main() {
    
char str[10],*s;
    
int p = 0;
    
s = str;
 
    
inttostr(1234,s,&p);
    
// s=IntToString(1234,s);
    
printf("%s\n",s);
}
 
int inttostr(int i, char *s, int *p)
{
    
if ( i/10 )
    
inttostr( i/10 , s, p);
    
s[*p] = i%10 + '0';
    
s[++*p] = '\0';
    
return 1;
}
 
char* IntToString(int value, char* string)
{
    
char* pos = string;
    
int radix = 1;
 
    
if (value == 0)
    
{
        *
string = '0';
        *
(string+1) = '\0';
        
return string;
    
}
 
    
while (radix <= value)
    
{
        
pos++;
        
radix *= 10;
    
}
 
    *
pos = '\0';
 
    
while (pos != string)
    
{
        *--
pos = value % 10 + '0';
        
value = value / 10;
    
}
 
    
return string;
}

运行结果:

[root@rhel5 inttostr]# make
cc -c 1.c
cc -o 1 1.o
[root@rhel5 inttostr]# ./1
1234
5月 30
  1. [root@localhost 2]# ./a
  2. pid: 4144 fork: 0
  3. pid: 4143 fork: 4144
  4. [root@localhost 2]# cat a.c
下载: a.c
  1.  #include <stdlib.h>
  2.  #include <stdio.h>
  3.  
  4.  main() {
  5.     int pid;
  6.  
  7.     switch ( pid = fork() ){
  8.        case -1:
  9.           printf("fork: error");
  10.           break;
  11.  
  12.        case 0:         /* child */
  13.           printf ("pid: %d fork: %d\n", getpid(), pid);
  14.           break;
  15.  
  16.        default:        /* parent */
  17.           printf("pid: %d fork: %d\n", getpid(), pid );
  18.           break;
  19.  
  20.     }
  21.     exit(0);
  22.  }

网上有些文章简单的说成fork调用一次,返回两次.

我的理解是fork调用以后,会创建一个新的子进程,将父进程(4143)的环境(fork调用之前的所有变量)复制(是复制!!!)到子进程(4144)中.这样,运行到fork函数的时候,我们就得到了2个进程(4144和4143)

然后由fork函数返回该进程(也就是父进程4143)创建的子进程pid(4144)

如果没有就返回0(比如4144)

如果异常,返回-1

由于是2个进程,每个进程的fork都会返回1次,总体看上去就像返回了2次一样.根据返回值的不同,可以让2个进程执行不同的代码.

以下是TCPechod.c中fork应用的节选

  1.  switch (fork()) {
  2.     case 0:         /* child */
  3.        (void) close(msock);
  4.        exit(TCPechod(ssock));
  5.     default:        /* parent */
  6.        (void) close(ssock);
  7.        break;
  8.     case -1:
  9.        errexit("fork: %s\n", strerror(errno));
  10.  }
5月 17

以下代码摘自 Internetworking With TCP/IP Vol III (Douglas E.Comer/David L.Stevens) 第7章

int main(int argc, char *argv[])
{
  
char *host = "localhost"; /* host to use if none supplied */
  
char *service = "echo"; /* default service name */
 
  
switch (argc) {
      
case 1:
        
host = "localhost";
        
break;
      
case 3:
        
service = argv[2];
        
/* FALL THROUGH */
      
case 2:
        
host = argv[1];
        
break;
      
default:
        
fprintf(stderr, "usage: TCPecho [host [port]]\n");
        
exit(1);
  
}
  
TCPecho(host, service);
  
exit(0);
}

代码第一眼看上去有点奇怪,switch的顺序1>3>2,而且case3没有break,稍微花点时间可以看出上下文的意思就明白为什么这么做了.仔细想了一下,感觉这样做是否值得呢?

1. 对于人而言,维护这样的代码无疑增加了开销

2. 对于编译器而言,这样写于常规写法比起来,并没有提高任何性能(如循环次数,处理命令的数量等)

3. 对于读者再说,不知道其他人或者作者的习惯如何,至少我是迷糊了一会儿的….(当然,这样写比较巧妙,但这样的技巧似乎没有带来任何收益?)