2015年7月31日星期五

[笔记] 关于 Soptify 和摆臂频率

Soptify 的教程,直接照着做就行了:
https://developer.spotify.com/technologies/spotify-ios-sdk/tutorial/

检测当前跑者摆臂频率:
这个是自己写的,逻辑上分为两个部分:

维护摆臂时间记录的数组:当垂直方向y的加速度绝对值大于0.8且距离上次有效的摆臂超过一定时间间隔时,记为摆臂有效,把当前时间存入一个NSMutableArray中。当这个NSMutableArray中的元素个数超过20时,删掉其中 index=0 的元素。

当前摆臂频率:根据上面提到的数组,取出第一个和最后一个元素,算时间间隔 interval1。再计算当前时刻和数组中最后一个元素的时间间隔 interval2。给出速度的定义为:每秒钟摆臂的次数。那么,这个速度的值就与 interval1 和 interval2 成正比。这个速度越大,说明摆臂的频率越低。

现在有一个问题就是,如果使用者一直竖着拿着手机,即使没有动,也会识别为摆臂频率很高。

GitHub链接:https://github.com/1992chenlu/TempoDemo

[笔记] 使用 CLLocationManager 实现 RunKeeper

这篇难度系数极低,主要关于如何维护使用者已经跑出的距离(distance 变量)……
算两个CLLocation之间的距离本来想用一个地球半径相关复杂公式算的,但是既然有现成的,还是省省吧……

用这个初始化CLLocationManager:
- (void)startLocationUpdates
{
    // Create the location manager if this object does not
    // already have one.
    if (self.locationManager == nil) {
        self.locationManager = [[CLLocationManager alloc] init];
    }
 
    self.locationManager.delegate = self;
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    self.locationManager.activityType = CLActivityTypeFitness;
 
    // Movement threshold for new events.
    self.locationManager.distanceFilter = 10; // meters
 
    [self.locationManager startUpdatingLocation];
}

用这段更新已经跑出的距离:
- (void)locationManager:(CLLocationManager *)manager
     didUpdateLocations:(NSArray *)locations
{
    for (CLLocation *newLocation in locations) {
        if (newLocation.horizontalAccuracy < 20) {
 
            // update distance
            if (self.locations.count > 0) {
                self.distance += [newLocation distanceFromLocation:self.locations.lastObject];
            }
 
            [self.locations addObject:newLocation];
        }
    }
}

注意:在使用CLLocationManager时,需要在Supporting File 的 info.plist 中加这样两行,否则没有办法用(调了好久才发现,还没搞清楚为啥)。

<!-- for requestAlwaysAuthorization -->
    <key>NSLocationAlwaysUsageDescription</key>
    <string>Explain for what are you using the user location</string>
    <!-- for requestWhenInUseAuthorization -->
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>Explain for what are you using the user location</string>

代码链接:https://gist.github.com/1992chenlu/2ec71e9dc5d3d6588160

Reference: http://www.raywenderlich.com/73984/make-app-like-runkeeper-part-1

[笔记] 关于 NSThread

这回的作业需要一直根据x,y,z三个方向的加速度维护一个变量,另外有个线程每隔一秒访问一次这个变量,根据变量的值判断输出音乐的频率。于是就先写了下面这么个程序练手。

下面这个东西干了这么个事情:分出两个Thread,都执行对value值+1,并打印的操作。
吐槽:笔者写似乎是个线程不安全的典型,请勿参考。

//
//  ViewController.m
//  MTTest
//
//  Created by 鲁辰 on 7/29/15.
//  Copyright (c) 2015 ChenLu. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, assign) NSUInteger value;

@end

@implementation ViewController
@synthesize value;

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    //NSThread
    [NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
    
    NSThread* myThread = [[NSThread alloc] initWithTarget:self
                                                   selector:@selector(run)
                                                     object:nil];
    [myThread start];

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)run {
    while (YES) {
        @synchronized(self) {
            value++;
        }
        NSThread *current = [NSThread currentThread];
        NSLog(@"Value: %lu, Thread: %@", (unsigned long)value, current);
        sleep(1);
    }
}

@end


代码链接:https://gist.github.com/1992chenlu/41b3adfb10d01ac36dda

Reference:
http://www.raywenderlich.com/60749/grand-central-dispatch-in-depth-part-1(这一篇很好,有时间应该细读)
http://www.cnblogs.com/likwo/archive/2011/11/01/2232309.html
http://sodecon.blogspot.com/2012/08/ios-multithreading-thread-safety-in-ios.html
http://www.libaocai.com/network/ios/2014/12/30/608

http://blog.csdn.net/zhangao0086/article/details/38904923(这篇关于GCD,还没搞明白T_T)

2015年7月29日星期三

[吐槽]YouTube Play On Repeat

YouTube video URL:




吐槽: 总是找不到YouTube重复播放的功能在哪里选,干脆写了一个……汗

https://gist.github.com/1992chenlu/0c3035086ea4c12b297e

2015年7月27日星期一

[LeetCode] Different Ways to Add Parentheses

Java Code:

public class Solution {
    public List<Integer> diffWaysToCompute(String input) {
        List<Integer> result = new ArrayList<Integer>();
        if (input == null || input.length() == 0) {
            return result;
        }
        
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            if (c != '+' && c != '-' && c != '*') {
                continue;
            }
            
            List<Integer> part1Result = 
                diffWaysToCompute(input.substring(0, i));
            List<Integer> part2Result = 
                diffWaysToCompute(input.substring(i + 1, input.length()));
            
            for (Integer m : part1Result) {
                for (Integer n : part2Result) {
                    if (c == '+') {
                        result.add(m + n);
                    } else if (c == '-') {
                        result.add(m - n);
                    } else if (c == '*') {
                        result.add(m * n);
                    }
                }
            }
        }
        
        if (result.size() == 0) {
            result.add(Integer.parseInt(input));
        }
        
        return result;
    }
}

reference:
https://leetcode.com/discuss/48477/a-recursive-java-solution-284-ms

[LeetCode] Search a 2D Matrix II

Java Code:

public class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        if (matrix == null || matrix.length == 0 
            || matrix[0].length == 0) {
            return false;
        }
        
        int i = 0;
        int j = matrix[0].length - 1;
        
        while (i < matrix.length && j >= 0) {
            if (matrix[i][j] == target) {
                return true;
            } else if (matrix[i][j] < target) {
                i++;
            } else {
                j--;
            }
        }
        
        return false;
    }
}

reference:
https://leetcode.com/discuss/47660/my-java-solution-using-binary-search

2015年7月24日星期五

[LeetCode] Maximum Product Subarray

Problem:

Find the contiguous subarray within an array (containing at least one number) which has the largest product.
For example, given the array [2,3,-2,4],
the contiguous subarray [2,3] has the largest product = 6.

Java Code:

public class Solution {
    public int maxProduct(int[] nums) {
        if (nums == null || nums.length == 0) {
            return -1;
        }
        
        int result = nums[0];
        int[] maxProduct = new int[nums.length];
        int[] minProduct = new int[nums.length];
        maxProduct[0] = nums[0];
        minProduct[0] = nums[0];
        
        for (int i = 1; i < nums.length; i++) {
            int[] tmp = new int[3];
            tmp[0] = nums[i];
            tmp[1] = nums[i] * maxProduct[i - 1];
            tmp[2] = nums[i] * minProduct[i - 1];
            
            Arrays.sort(tmp);
            
            result = Math.max(result, tmp[2]);
            maxProduct[i] = tmp[2];
            minProduct[i] = tmp[0];
        }
        
        return result;
    }
}

reference: https://leetcode.com/discuss/41102/share-accepted-dp-java-o-n-solution

2015年7月22日星期三

"Layers" of Cache

There are in fact many layers of cache in a modern PC. This does not even include looking at caches included on some peripherals, such as hard disks. Each layer is closer to the processor and faster than the layer below it. Each layer also caches the layers below it, due to its increased speed relative to the lower levels:

Level
Devices Cached
Level 1 Cache
Level 2 Cache, System RAM, Hard Disk / CD-ROM
Level 2 Cache
System RAM, Hard Disk / CD-ROM
System RAM
Hard Disk / CD-ROM
Hard Disk / CD-ROM
--



What happens in general terms is this. The processor requests a piece of information. The first place it looks is in the level 1 cache, since it is the fastest. If it finds it there (called a hit on the cache), great; it uses it with no performance delay. If not, it's a miss and the level 2 cache is searched. If it finds it there (level 2 "hit"), it is able to carry on with relatively little delay. Otherwise, it must issue a request to read it from the system RAM. The system RAM may in turn either have the information available or have to get it from the still slower hard disk or CD-ROM. The mechanics of how the processor (really the chipset controlling the cache and memory) "look" for the information in these various places is discussed here.

It is important to realize just how slow some of these devices are compared to the processor. Even the fastest hard disks have an access time measuring around 10 milliseconds. If it has to wait 10 milliseconds, a 200 MHz processor will waste 2 million clock cycles! And CD-ROMs are generally at least 10 times slower. This is why using caches to avoid accesses to these slow devices is so crucial.

Caching actually goes even beyond the level of the hardware. For example, your web browser uses caching itself, in fact, two levels of caching! Since loading a web page over the Internet is very slow for most people, the browser will hold recently-accessed pages to save it having to re-access them. It checks first in its memory cache and then in its disk cache to see if it already has a copy of the page you want. Only if it does not find the page will it actually go to the Internet to retrieve it.

reference: http://www.pcguide.com/ref/mbsys/cache/layers.htm

Difference between Virtual Memory and Physical Memory

Virtual memory is, among other things, an abstraction to give the programmer the illusion of having infinite memory available on their system.
Virtual memory mappings are made to correspond to actual physical addresses. The operating system creates and deals with these mappings - utilizing the page table, among other data structures to maintain the mappings. Virtual memory mappings are always found in the page table or some similar data structure (in case of other implementations of virtual memory, we maybe shouldn't call it the "page table"). The page table is in physical memory as well - often in kernel-reserved spaces that user programs cannot write over.
Virtual memory is typically larger than physical memory - there wouldn't be much reason for virtual memory mappings if virtual memory and physical memory were the same size.
Only the needed part of a program is resident in memory, typically - this is a topic called "paging". Virtual memory and paging are tightly related, but not the same topic. There are other implementations of virtual memory, such as segmentation.
I could be assuming wrong here, but I'd bet the things you are finding hard to wrap your head around have to do with specific implementations of virtual memory, most likely paging. There is no one way to do paging - there are many implementations and the one your textbook describes is likely not the same as the one that appears in real OSes like Linux/Windows - there are probably subtle differences.

2015年7月21日星期二

Database/SQL Interview Questions and Answers

1. What is a field in database?
A field is an area within a record reserved for a specific piece of data.

2. What is a record in a database?
A record is the collection of values/fields of a specific entity.

3. What is a table in database?
A table is a collection of records of a specific type.

4. What is a database transaction?
Database transaction takes database from one state to another. At the end of the transaction the system must be in the prior state if the transaction fails or the status of the system reflect the successful completion if the transaction goes through.

5. What are properties of a transaction? (ACID properties)
(1) Atomicity
A transaction consists of many steps. When all the steps in a transaction get completed, it will get reflected in DB or if any step fails, all the transactions are rolled back.

(2) Consistency (* What is the difference between consistency and atomocity?)
The database will move from one consistent state to another, if the transaction succeeds and remainin the original state, if transaction fails.

(3) Isolation
Every transaction should operate as if it is the only transaction in the system.

(4) Durability
Once a transaction has been completed successfully, the update rows/records must be available for all the other transactions on a permanent basis.

5. What is a composite key?
A composite primary key is a type of candidate key, which represents a set of columns whose values uniquely identified every row in a table.
e.g. Combination of "employee id" and "employee name" in a table is combined to uniquely to identify a row its called a composite key.

6. What is a foreign key?
A foreign key is a column (or columns) that references a column (most often the primary key) of another table.

7. What is a unique key?
Unique key is same as primary with the difference being the existence of null.

8. SQL insert statement:
SQL INSERT statement is used to add rows to a table. For a full row insert, SQL query should start with "insert into" statement followed by name and value command. The insert can be used in several ways:
(1) to insert a single complete row
(2) to insert a single partial row

9. SQL update statement:

10. SQL delete statement:

11. What are wild cards used in database for pattern matching?
SQL like operator is used for pattern matching.

12. Define join and explain different type of joins:
In order to avoid data duplications, data is stored in related tables. Join keyword is used to fetch data from related tables. "join" return rows when there is at least one match in both table. Type of joins are:
(1) right join: return all rows from the right table, even if there are no matches in the left table
(2) left join: return all rows from the left table even if there are no matches in the right table
(3) full join: return rows when there is a match in one of the tables

13. What is self join?
Self join is query used to join a table itself.
(* When will self join be used?)

14. What is cross join?(*)

15. What is a view?
The views are virtual tables. Unlike tables that contain data, views simply contain queries that dynamically retrieve data when used.

16. What is a materialized view?
Materialized views are also a view but are disk based. Materialized views get updates on specific duration, base upon the interval specified in the query definition.

17. What are the advantages and disadvantages of views in a database?
Advantages:
(1) Views don't store data in a physical location
(2) The view can be used to hide some of the columns from the table
(3) Views can provide access restriction, since data insertion, update and deletion is not possible with the view.

Disadvantages:
(1) When a table is dropped, associate view become irrelevant.
(2) Since the view is created when a query requesting data from view is triggered, its a bit slow
(3) When viwes are created for large tables, it occupies memory

18. What is a stored procedure?
Stored procedure is a function which contains a collection of SQL queries. The procedure can take inputs, process tham and send back output.

19. What are the advantages of a stored procedure?
Stored procedure are precompiled and stored in the database. This enables the database to execute the queries much faster. Since many queries can be included in a stored procedure, round trip time to execute multiple queries from source code to database and back is avoided.

20. What is a trigger?
Database triggers are sets of commands that get executed when an event (before insert, after insert, on update, on delete of a row) occurs on a table, vies.

21. Explain the difference between delete, truncate and drop commands?
Once delete operation is performed, commit and rollback can be performed to retrieve data.
Once truncate statement is executed, commit and rollback statement cannot be performed. Where condition can be used along with delete statement but it can't be used with truncate statement.
Drop command is used to drop the table or keys like primary foreign key from a table.

22. What is the difference between cluster and non cluster index?
A cluster index reorders the way records in the table are physically stored. There can be only one clustered index per table. It makes data retrieval faster.
A non clustered index does not alter the way it was stored but creates a completely separate object within the table. As a result insert and update command will be faster.

23. What is union, minus and interact command?
minus operator is used to return rows from the first query but not from the second query.
intersect operator is used to return rows returned by both queries.

reference: http://a4academics.com/interview-questions/53-database-and-sql/411-sql-interview-questions-and-answers-database

24. 1NF/2NF/3NF
First normal form (1NF) is a property of a relation in a relational database. A relation is in first normal form if the domain of each attribute contains only atomic values, and the value of each attribute contains only a single value from that domain.

A table that is in first normal form (1NF) must meet additional criteria if it is to qualify for second normal form. Specifically: a table is in 2NF if and only if it is in 1NF and no non-prime attribute is dependent on any proper subset of any candidate key of the table. A non-prime attribute of a table is an attribute that is not a part of any candidate key of the table.
Put simply, a table is in 2NF if and only if it is in 1NF and every non-prime attribute of the table is dependent on the whole of every candidate key.

Third normal form(3NF) is a normal form used in normalizing a database design to reduce the duplication of data and ensure referential integrity by ensuring that the entity is in second normal form and all the attributes in a table are determined only by the candidate keys of that table and not by any non-prime attributes.

Linux系统生成,进(线)程同步与通信,并发程序的誊抄,文件目录操作


0 Linux系统生成

步骤:
(1)安装Linux系统Ubuntu10.12
(2)使用ctrl+alt+T打开终端
(3)设置root用户及root用户密码:使用的命令如图所示

(4)进入root用户
(5)把源码包解压到 /usr/src/linux-3.6.3

(6)编译内核:使用make命令
(7)安装编译好的内核
(8)查看内核版本

1 实验一LINUX系统用户界面 实验二进(线)程同步与通信

1.1 实验目的

       1、掌握Linux系统用户界面中键盘命令的使用。
       2、学会一种Linux下的编程环境。
       3、掌握Linux下进(线)程的概念。
       4、了解Linux进程同步与通信的主要机制,并通过信号灯操作实现进程间的同步与互斥。

1.2 预备知识

1.2.1 Linux下的信号灯及其P、V操作
1. 1 PV操作定义
P操作
V操作
   void P(int semid,int index)
  {    struct sembuf sem;     
        sem.sem_num = index;
        sem.sem_op = -1;   
        sem.sem_flg = 0;      //:操作标记:0IPC_NOWAIT  
        semop(semid,&sem,1);          //1:表示执行命令的个数
        return;
}
   void V(int semid,int index)
  {    struct sembuf sem;     
        sem.sem_num = index;
        sem.sem_op =  1;
        sem.sem_flg = 0;     
       semop(semid,&sem,1);    
       return;
}



1.2.2 线程
1. 2 线程相关函数
线程创建
pthread_create(pthread_t  *thread, pthread_attr_t         *attr,
       void *(*start_routine)(void *),void *arg);
线程挂起
pthread_join(pthread_t th, void **thread_retrun);

1.2.3 共享内存
使用共享内存是运行在同一计算机上的进程进行进程间通信的最快的方法,shmget与shmat 系统调用。

1.2.4 进程控制
   fork与execv系统调用

1.2.5 编译、编辑、调试
1. 3 编译、编辑、调试
编译
cc –o  test  -g test.c –lpthread  
cc –o sub1 sub1.c
编辑
vi
调试
gdb

1.3 实验内容

实验一的程序要求:
    两个线程,共享公共变量a
    线程1负责计算(+1)
    线程2负责打印
实现:
       1、线程的同步与互斥
       2、进程的同步与互斥
       3、子进程的创建
1.4 运行结果

1. 1 运行结果

1.5 源代码
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <linux/sem.h>
#define LOOPS 10
void P(int semid,int index);
void V(int semid,int index);
int semid;int a=0;
pthread_t p1,p2;
void *subp1();void *subp2();
void P(int semid,int index)
 {         
           struct sembuf sem;     
        sem.sem_num = index;
        sem.sem_op = -1;    
        sem.sem_flg = 0;       //:操作标记:0IPC_NOWAIT  
        semop(semid,&sem,1);               //1:表示执行命令的个数    
        return;
}
void V(int semid,int index)
{        
           struct sembuf sem;     
        sem.sem_num = index;
        sem.sem_op =  1;
        sem.sem_flg = 0;      
              semop(semid,&sem,1);         
              return;
}
void *subp1()
{        
           int i,j;         
           for (i=0;  i< LOOPS;i++)
           {                   
                     P(semid,0);                    
                     printf("subp1:a=%d\n",a); 
                     V(semid,1);         
           }        
           return;
}
void *subp2()
{        
           int i,j;         
           for (i=0;i<LOOPS;i++)
           {                   
                    P(semid,1);                    
                     a+=1;                    
                     V(semid,0);         
           }
           return;
}
main()
{        
           union semun  semopts;      
           int res;
           semid =semget(11,2,IPC_CREAT|0666);
           semopts.val = 0;
           res=semctl(semid,0,SETVAL,semopts);
           semopts.val = 1;
           res=semctl(semid,1,SETVAL,semopts);           
           pthread_create(&p1,NULL,subp1,NULL);      
           pthread_create(&p2,NULL,subp2,NULL);      
           pthread_join(p1,NULL);       
           pthread_join(p2,NULL);       
           semctl(semid,0,IPC_RMID,0);
}

2在linux下编程实现P98  4-11


2.1 实验目的
了解并发程序的执行过程和实现原理

2.2 预备知识

2.2.1 并发程序的誊抄


2. 1  誊抄过程
get程序:负责从输入序列f中读取字符并送到缓冲区s中;
copy程序:把缓冲区s中的数据复制到缓冲区t中去;
put程序:从缓冲区t中取出数据打印。

2.2.2 誊抄的实现

2. 2 誊抄的实现

在相应的圆圈对应的进程中,通过修改箭头上对应序号的信号灯控制进程的运行,设有4个信号灯分别为0、1、2、3
在进程中对信号灯的控制可简写为:
get()
{
           p(0);
           get操作;
           v(2);
}
copy()
{
           p(1);
           p(2);
           copy操作;
           v(0);
           v(3);
}
put()
{
           p(3);
           put操作;
           v(1);
}
通过设置信号灯0的初值和利用copy对信号灯0v操作,使得当信号灯0的资源个数>0时,可以进行get操作
通过设置信号灯12的初值和利用put对信号灯1v操作、利用get对信号灯2v操作,使得当信号灯1和信号灯2的资源个数均>0时,可以进行copy操作
通过设置信号灯3的初值和利用copy对信号灯3v操作,使得当信号灯3的资源个数>0时,可以进行put操作

2.3 实验内容

1、实现: main、get、copy、put 4个函数
2、将这四个函数编译链接(使用makefile)
2.4 运行结果

2. 3 运行结果
使用./main打开程序

2.5 源代码
main.c
#include<stdio.h>
#include<stdlib.h>
#include<linux/shm.h>
#include<sys/types.h>
#include<linux/sem.h>
#define LOOPS 10
#define IPCKEY (key_t)0x11
#define SHMKEY1 (key_t)0x222
#define SHMKEY2 (key_t)0x333
void P(int semid,int index);
void V(int semid,int index);
int semid;

void V(int semid,int index)
{
    struct sembuf sem;
    sem.sem_num = index;/*信号灯数组灯的一个索引,指明哪个信号灯*/
    sem.sem_op = 1;/*加到当前信号灯的数值*/
    sem.sem_flg = 0;
    semop(semid,&sem,1);
    return;
}
void P(int semid,int index)
{
    struct sembuf sem;
    sem.sem_num = index;
    sem.sem_op = -1;
    sem.sem_flg = 0;
    semop(semid,&sem,1);
    return;
}

int main(void)
{
    union semun semopts;
    int res,i;
    struct shmid_ds *buf;
    int cmd;
    int shmid1,shmid2;
    char *s,*t,ss[]="";
    pid_t p1,p2,p3;
   
   
    semid = semget(IPCKEY,4,IPC_CREAT|0666);  
    semopts.val = 1;
    res = semctl(semid,0,SETVAL,semopts);   
    semopts.val = 1;
    res = semctl(semid,1,SETVAL,semopts); 
    semopts.val = 0;
    res = semctl(semid,2,SETVAL,semopts);   
    semopts.val = 0;
    res = semctl(semid,3,SETVAL,semopts); 
    shmid1 = shmget(SHMKEY1,sizeof(char),IPC_CREAT|0666);  
    s=(char *)shmat(shmid1,NULL,SHM_R|SHM_W);
    shmid2 = shmget(SHMKEY2,sizeof(char),IPC_CREAT|0666);
    t=(char *)shmat(shmid2,NULL,SHM_R|SHM_W);
   
 
   
    if((p1=fork()) == 0){
        execv("./get",NULL);
        }
     else
     {
         if((p2=fork()) == 0){
             execv("./copy",NULL);
              }
          else
          {
              if((p3=fork())==0){
                 execv("./put",NULL);
                 }
           }
      }
      p1=wait(&p1);
      p2=wait(&p2);
      p3=wait(&p3);
      /*for(i=0;i<3;i++)
      {
          while(-1!=wait())
              ;
      }*/
      if(semctl(semid,0,IPC_RMID,0)<0)
      printf("error");
      shmctl(shmid1,IPC_RMID,0);
      shmctl(shmid2,IPC_RMID,0);
      return 0;
}

get.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<linux/sem.h>
#include<linux/shm.h>
#define LOOPS 10
#define IPCKEY (key_t)0x11
#define SHMKEY1 (key_t)0x222
#define SHMKEY2 (key_t)0x333
void P(int semid,int index);
void V(int semid,int index);
int semid;

void V(int semid,int index)
{
    struct sembuf sem;
    sem.sem_num = index;/*信号灯数组灯的一个索引,指明哪个信号灯*/
    sem.sem_op = 1;/*加到当前信号灯的数值*/
    sem.sem_flg = 0;
    semop(semid,&sem,1);
    return;
}
void P(int semid,int index)
{
    struct sembuf sem;
    sem.sem_num = index;
    sem.sem_op = -1;
    sem.sem_flg = 0;
    semop(semid,&sem,1);
    return;
}
int main(void)
{
   
    int i=0;
    int shmid1;
    char *s,*t,str[]="linux!";/*str为输入的字符,实现一个一个字符的输入,输出,st指针当单个字符使用,即s[0],t[0]*/
   
    semid = semget(IPCKEY,4,IPC_CREAT|0666);
    shmid1 = shmget(SHMKEY1,sizeof(char),IPC_CREAT|0666);
    s=(char *)shmat(shmid1,NULL,SHM_R|SHM_W);/* 绑定到共享内存块 */
   
    do
    {
        P(semid,0);     
        s[0]=str[i];
        printf("get\n");
        i++;      
        V(semid,2);
       
     }while(s[0]!='\0');
}     


copy.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<linux/sem.h>
#include<linux/shm.h>
#define LOOPS 10
#define IPCKEY (key_t)0x11
#define SHMKEY1 (key_t)0x222
#define SHMKEY2 (key_t)0x333
void P(int semid,int index);
void V(int semid,int index);
int semid;

void V(int semid,int index)
{
    struct sembuf sem;
    sem.sem_num = index;/*信号灯数组灯的一个索引,指明哪个信号灯*/
    sem.sem_op = 1;/*加到当前信号灯的数值*/
    sem.sem_flg = 0;
    semop(semid,&sem,1);
    return;
}
void P(int semid,int index)
{
    struct sembuf sem;
    sem.sem_num = index;
    sem.sem_op = -1;
    sem.sem_flg = 0;
    semop(semid,&sem,1);
    return;
}
int main(void)
{
   
    int j=0;
    int shmid1,shmid2;
    char *s,*t;
 
    semid = semget(IPCKEY,4,IPC_CREAT|0666);
    shmid1 = shmget(SHMKEY1,sizeof(char),IPC_CREAT|0666);
    s=(char *)shmat(shmid1,NULL,SHM_R|SHM_W);/* 绑定到共享内存块 */
    shmid2 = shmget(SHMKEY2,sizeof(char),IPC_CREAT|0666);
    t=(char *)shmat(shmid2,NULL,SHM_R|SHM_W);
    do
    {
    
        P(semid,1);
        P(semid,2);
        strcpy(t,s);
        printf("copy\n");
        V(semid,0);
        V(semid,3);
      
     }while(t[0]!='\0');
    
}


put.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<linux/sem.h>
#include<linux/shm.h>
#define LOOPS 10
#define IPCKEY (key_t)0x11
#define SHMKEY1 (key_t)0x222
#define SHMKEY2 (key_t)0x333
void P(int semid,int index);
void V(int semid,int index);
int semid;


void V(int semid,int index)
{
    struct sembuf sem;
    sem.sem_num = index;/*信号灯数组灯的一个索引,指明哪个信号灯*/
    sem.sem_op = 1;/*加到当前信号灯的数值*/
    sem.sem_flg = 0;
    semop(semid,&sem,1);
    return;
}
void P(int semid,int index)
{
    struct sembuf sem;
    sem.sem_num = index;
    sem.sem_op = -1;
    sem.sem_flg = 0;
    semop(semid,&sem,1);
    return;
}
int main(void)
{
   
    int k=0;
    int shmid1,shmid2;
    char *s,*t;

    semid = semget(IPCKEY,4,IPC_CREAT|0666);
    shmid2 = shmget(SHMKEY2,sizeof(char),IPC_CREAT|0666);
    t=(char *)shmat(shmid2,NULL,SHM_R|SHM_W);/* 绑定到共享内存块 */
    do
    {
        /*if(t[0]=='\0')break;*/
        P(semid,3);
        if(t[0]!='\0')printf("put---->%c\n",*t);
        else printf("put---->\\0\n");
        V(semid,1);
      
     }while(t[0]!='\0');
    
 }
             
makefile
all:get copy put main
           echo "complete"
get:get.o
           gcc -o get get.o
copy:copy.o
           gcc -o copy copy.o
put:put.o
           gcc -o put put.o
main:main.o
           gcc -o main main.o
get.o:get.c
           gcc -c get.c
copy.o:copy.c
           gcc -c copy.c
put.o:put.c
           gcc -c put.c
main.o:main.c
           gcc -c main.c

3 实验三  Linux文件目录操作


3.1 实验目的、实验要求

3.1.1实验目的
了解并掌握Linux文件目录结构。

3.1.2 实验要求
了解Linux文件系统与目录操作:
(1) Linux文件系统 :文件属性;
(2)Linux目录结构:目录文件;
(3)目录相关函数接口;

3.2 实验内容
1、熟悉Linux文件系统的使用;
2、了解Linux文件系统目录结构;
3、编程实现目录查询命令;
•     功能类似ls -lR;
•     查询指定目录下的文件及子目录信息;
    显示文件的类型、大小、时间等信息;
•     递归显示子目录中的文件信息;

3.3 预备知识

3.3.1 Linux文件属性接口

3. 1 文件属性接口
函数
功能
int fstat(int fildes,struct stat *buf);
返回文件描述符相关的文件的状态信息
int lstat(const char *path, struct stat *buf);
如读取到了符号连接,读取符号连接本身的状态信息
int stat(const char *path, struct stat *buf);
如读取到了符号连接,读取的是符号连接指向文件的信息

stat结构体几乎保存了所有的文件状态信息:
本程序中主要用到st_mode 文件的权限信息和类型信息,检查类型时使用S_ISDIR(); 宏,检查是否是目录

3.3.2 Linux目录结构接口
3. 2 目录结构接口
函数
功能
DIR *opendir(const char *name);

通过路径打开一个目录,返回一个DIR结构体指针(目录流),失败返回NULL
struct dirent *readdir(DIR *)

读取目录中的下一个目录项,没有目录项可以读取时,返回为NULL
int chdir(const char *path);

改变目录,与用户通过cd命令改变目录一样,程序也可以通过chdir来改变目录,这样使得 fopen(),opendir(),这里需要路径的系统调用,可以使用相对于当前目录的相对路径打开文件(目录)
int closedir(DIR*)
关闭目录流

在本程序中,用到结构dirent中的char   d_name[256]; (文件名)项

3.4 运行结果

3. 1 运行结果

3.5 源代码
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>

void printdir(char *dir, int depth){
    DIR *dp;
    struct dirent *entry;
    struct stat statbuf;
  
    if  (((dp = opendir(dir)))== NULL){     // opendir
        printf("Open Dir Failed!\n");
        return ;
    }
    chdir(dir);   //chdir

while( (entry=readdir(dp))!=NULL){   //readdir
           lstat(entry->d_name,&statbuf);
           if(S_ISDIR(statbuf.st_mode)){
            if(strcmp(entry->d_name,"..")==0||strcmp(entry->d_name,".")==0)
                 continue;
            printf("DIR DEPTH:          %d    ",depth);
           printf("DIR NAME:    %s\n",entry->d_name);
            printdir(entry->d_name,depth+1);
        }  
            else
           {
            printf("FILE DEPTH:         %d    ",depth);
           printf("FILE NAME:  %s\n",entry->d_name);
                     }    }
    chdir("..");//chdir
    closedir(dp); //closedir
}

int main(void){
    char a[50];
           printf("Input Dir Name!\n");
           scanf("%s",a);
           printdir(a,0);
           return 0;
}