728x90

이전 실습과제

1. 주가 정보 크롤링 프로그램 작성 matplotlib과 seaborn을 이용해 csv jupyter그래프 표시

2. sysstat data를 dataframe으로 바꾸어서 동일하게 분석

필드 데이터 실습

 

* sysstat 성능 상황 기록

- sar 명령어로 10분간격 확인 가능

ref : platformengineer.tistory.com/46 (sysstat 사용법)

 

 

apt --installed list | grep sysstat

apt-get install sysstat -y

vi /etc/default/sysstat

ENABLED="false" -> "true"

service sysstat restart

/var/log/sysstat에서 확인 가능

 

 

 

----

1. colab 사용

2. git repo 와 colap연동

3. ml 기본코드 이해

4. sklearn 빌트인 모델 사용 코드 작성 regression, classification

 

 

과제

1. load_boston, load_innerud, fetch_california_housing 데이터 가져와 분석, 모델 선택하여 regression 학습

2. sysstat.data 를 dataframe으로 바꿔서 동일하게 분석하기

 

 

 

 

 

colab

- gpu 무료 제공

- jupyter notebook

 

 

 

colab과 깃랩연동

- 기존 .ssh파일 모든 사용자 r권한 주기

   chmod a+r ~/.ssh/*

- .ssh 아래 파일들 가져오기

 

* filzilla 사용

-  사이트 관리자에 sftp로 추가. 구글 클라우드 인스턴스 ppk, pem 사용하여 연결

blog.naver.com/PostView.nhn?blogId=appnada&logNo=221194916635&parentCategoryNo=&categoryNo=14&viewDate=&isShowPopularPosts=true&from=search

 

 

* scp의 경우

scp -i 키 계정@구글클라우드플랫폼주소:/home/디렉토리/파일 /home/옮길디렉토리

 

 

 

 

구글 드라이브 마운트 시키기

 

from google.colab import drive

import os, sys

drive.mount("/content/mnt")

nb_path="/content/notebooks"

os.symlink("/contnent/mnt/My Drive/Colab Notebooks", nb_path)

sys.path.insert(0, nb_path)

 

 

 

 

 

!cd /content/notebooks/

!git config --global user.name "name"

!git config --global user.email "email"

 

** 나는 /content/notebooks이 안되서 심볼릭 링크가 아니라 그냥 원본 폴더로 cd했다. 아래도 동일

!cd /content/mnt/My\ Drive/Colab\ Notebooks

-> 보니까 심볼릭 링크를 만들때 /contnent/mnt/My drive/ ...로 오타를 내서 잘못됫더라 고쳤더니 기존 코드대로 동작

 

!mkdir ~/.ssh

!cp /content/mnt/"My Drive"/id_rsa ~/.ssh

!cp /content/mnt/"My Drive"/id_rsa.pub ~/.ssh

!cp /content/mnt/"My Drive"/authorized_keys ~/.ssh

!cp /content/mnt/"My Drive"/known_hosts ~/.ssh

!ls ~/.ssh

 

 

!git clone 클론할 저장소 /content/notebooks/폴더명

 

 

# -C는 저장소 명시

!git -C /content/notebooks/****** add .

!git -C /content/notebooks/****** pull

!git -C /content/notebooks/****** status

!git -C /content/notebooks/******* commit -m "message"

!git -C /content/notebooks/****** push

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

------------------

server refused 문제

- 중간에 하다가 퍼블릭키 문제로 서버 거부가 발생

- 클라이언트 ppk와 서버의 pub가 매칭이 안됨 + 서버의 공개키가 없어져있었음.

 

- 아래 링크 참고하여 해결

 1. 푸티 키젠으로 새 pub, ppk 생성

 2. 서버 ssh에 새 pub 등록

 3. 웹으로 서버 접속하여 authorized_key에 새 pub 복붙

 4. sshd restart

 

opentutorials.org/module/432/3742

serverfault.com/questions/955843/putty-server-refused-our-key-google-cloud-platform-compute-engine-instance

 

---------------

 

 

 

 

 

 

1. load_boston, load_innerud, fetch_california_housing 데이터 가져와 분석, 모델 선택하여 regression 학습

 

 

 

california housing regression

1. 라이브러리 임포트

 

2. 데이터 준비하기

 

3. 데이터 확인

 

 

 

 

 

4. 회귀 모델 생성 학습, 예측, 시각화까지

 단순 선형 회귀 모델

 

 라쏘라르 모델

 

 

 

 

 

 

 

 

 

유방암 데이터셋 SVM으로 분류하기 

1. 라이브러리 임포트

 

2. 데이터 준비

 

 

 

 

 

3. SVM 학습, 분류, 시각화

 

 

 

 

 

 

 

 

 

 

 

300x250
728x90

목표

- 머신/딥러닝 기본 이론

- 데이터 취득, 분석

- matplotlib, seaborn 시각화 까지

* 숫자가 아닌 필드를 숫자로 바꾸어주자!!

 

 

 

 

빠트린거

- 볼륨 설정을 하는데 자꾸 permission denied 발생

 

 

 

 

도커 이미지 내의 

 

jovyan 폴더를 권한 777주는게 아니라

 

치프트키 님의 글을 보니 호스트 볼륨 폴더에 권한을 주어야되더라

 

chiftkey.tistory.com/3

 

 

일단 이 문재는 해결했고..

 

 

 

 

 

 

구글 클라우드 플랫폼에서 방화벽 포트도 열어주고

 

도커 런시 포트도 연결 시켜주었으나 페이지에 접속하지 못하고 있다

 

 

* 방화벽도 설정하고, jupyter 외부접속도 허용도하고

포트 포워딩도 다 했는데 왜안되나 했는더니

 

방화벽 규칙 대상을 

 

네트워크의 모든 인스턴스 적용을 안해놔서 그렇더라 

 

80 포트는 잘되는데 내가 만든 8888포트 허용 규칙이 왜안되나 했다

 

 

 

 

 

 

 

 

 docker run -p 8888:8888 --memory=2g -v ~/gitlab/ssac-pytorch-1st/exercise:/ds --name hello /jaimeps/rl-gym

 

 

 

sklearn dataset

- 아래 링크서 많이 제공

scikit-learn.org/stable/datasets/index.html

 

 

 

sklearn dataset 호출시

- load : simple data

- fetch : real world data

 

 

 

 

 

 

df.info()

- 데이터 별 개수와 타입

df.describe()

- 기술 통계량

 

 

df.plot()

- 데이터 프레임은 plot도 가능 

 

 

sns.pairplot(df)

- 변수간 모든 상관관계 plot

- 변수 자기 자신은 그냥 히스토그램 플롯

- target에 대해 hue 지정시

 

 

 

 

와인 데이터 연습

 

1. 데이터 로드

2. 데이터 정보 보기

3. 데이터 프레임 만들기

 

 

* 그룹별 크기 출력

 

4. 시각화

4.1 sns.pairplot(df)

 

 

 

 

 

 

 

300x250
728x90

 

 

지난번 수업을 들을때

 

구글 클라우드 플랫폼에서 가상 머신을 만들고

 

가상 머신에서 도커를 설치해서 이것저것을 했었는데

 

나는 계정 문제 때문에 가상머신 만드는 부분을 제대로 하지를 못했었다.

 

 

 

 

이제 와서 급하게 가상 머신을 만들고 ssh 키 등록해서 접속하는 방법을 

 

대충 검색해서 해봤다.

 

 

가상머신 만드는 방법은

 

마스터 서님의 글을 보고 참고해서 진행할 수 있었다.

 

brunch.co.kr/@topasvga/168

 

3년전의 글이긴 하지만 대부분 지금도 비슷하니 문제는 없었고 

 

 

 

 

 

조금 주의해야 하는 부분은

 

ssh키를 설정해 주어야 하는데

 

 

 

지난번 수업때 보니 

 

puttygen으로 개인키와 공개키를 만들어서 하더라

 

그런데 하는 방법은 생각 안나고 잠깐 찾아봣는데

 

kiseon님이 잘 정리해놓으신 글이 있었다.

 

medium.com/@kiseon_twt/gcp-putty-setup-%ED%95%98%EA%B8%B0-25c489e06059

 

이 글 참고해서 공개키 등록하고 가상머신 생성 후

 

푸티로 들어왔다.

 

 

 

 

안그래도 터미널을 잘 안쓰는데 iterm을 쓰다가

 

putty가 너무 밋밋하더라

 

한번 테마를 추가해보려고 조금 찾아봤다.

 

 

 

putty 테마 적용 방법에 대해서 

 

조길상 님이 잘 정리해놓으신 글이 있더라

 

m.blog.naver.com/jogilsang/221853657930

 

하면서 주의해야하는 점은

 

테마 적용전 만들어둔 세팅에는 적용이 안된다고 한다.

 

테마를 적용후 다시 인스턴스 세팅을 만들어서 저장해주자.

 

 

 

큰 차이가 있는지는 모르겠는데 아까보다는 나아보인다

 

 

 

도커를 설치해야되니

 

이전에 썻던 글을 보면서 하고

 

throwexception.tistory.com/986

* 정확히는 도커 공식 홈페이지를 보면서 ..

 

 

도커를 설치하는 중간에 순간 400mb나 된다고 해서 잠깐 놀랏다.

 

핫스팟으로 인터넷 사용 중이라 데이터 고갈되는게 아닌가 했는데

 

지금 구글 인스턴스에 접속해서 쓰고있는걸 잊고 있었다.

 

 

 

 

이미지 가져오고, 들어갓다가 나오기도 하고, 삭제하고

 

오랜만에 하면서 잘 생각은 안나지만

 

이전에 대충이나마 정리해둬서 다행이다 

 

 

 

 

---------

 

맥북이 있다보니 그래도 putty보다는 iterm으로 접속해서 사용하고 싶은데

 

지난번에 ppk를 어떻게 다룰지를 몰라서

 

제대로 찾지 못하고 한참 해맷었다.

 

blog.naver.com/windi97/220976620976

 

이 글을 참고해서 진행을 하는데

 

무슨 이유에서인지 putty부터 접속이 안되더라

 

일단 윈도우에서 ppk 만들었으니 여기서 pem을 만들고 내일 맥에서 써보려고 한다.

 

참고 : aws.amazon.com/ko/premiumsupport/knowledge-center/convert-pem-file-into-ppk/

 

 

 

 

 

 

300x250
728x90

실습 과제물...

 

1. fluentd와 몽고db로 로그 취합하는 시스템 구축

2. jupyter/datascience-notebook or jaimeps/rl-gym 등 데이터 사이언스 관련 컨테이너를 public cloud에서 구동하고 jupyter에서 접속한다.

3. pytorch를 설치한 이미지로 컨테이너를 구동한다.

 

 

 

 

www.docker.com/resources/what-container

 

도커란 무엇인가

 

 

컨테이너

- 의존성과 패키지코드가 함께 있는 추상화

- 각 머신처럼 동작 가능. os 커널은 공유

 

 

 

 

 

클라우드 컴퓨팅

- aws, 에저, 구글 클라우드 엔진

 => 구글 클라우드 엔진이 후함

 

console.cloud.google.com/

 

 

도커 설치하기 

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

 

sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

 

 $ sudo apt-get update
 $ sudo apt-get install docker-ce

 

 

ref: docs.docker.com/engine/install/ubuntu/

 

Install Docker Engine on Ubuntu

 

docs.docker.com

 

 

 

도커에는

 

이미지와 컨테이너가 있다..

 

 

컨테이너 들어오기

 

docker run -i -t ubuntu:14.04

* -i : interactive

* -t : terminal

 

기존 환경에서 우분투 14.04 컨테이너로 들어왔다.

 

 

exit 명령의 경우 컨테이너 자체가 종료된다.

 

 

컨테이너

 

어플리케이션 실행하고 싶은데 실행하기 위한 공간

 

 

 

ctrl pq를 하면 다시 컨테이너 밖으로 나온다..

(exit와 달리 컨테이너 종료 x)

 

 

다시 캡처해서 보면

 

아까 컨테이너가 살아있다.

 

 

 

docker ps -a

exit 시킨 컨테이너도 나온다.

 

 

docker rm {id, name} 컨테이너 삭제하기.

 

 

삭제하려했더니 동작중이라 한다 

 

 

 

docker stop id/name

 

stop부터 해주고 다시 삭제

 

 

stoic_williamson 컨테이너 삭제 ok

 

 

 

 

centos 이미지 가져오기

 

docker pull centos:7

 

 

 

docker image ls

- 가지고 있는 이미지 목록 보기

-> 우분투 버전 14.04와 센토스 7이 추가되어있다.

 

 

docker run -it centos:latest

 

센토스 컨테이너에 들어왔다가

 

다시 컨트롤 pq로 나오자.

 

docker ps해보면 centos:latest가 돌아가고있다.

 

 

docker container prune

쓰지 않는 컨테이너 지우기

 

 

docker attach 아이디/이름 : 다시 컨테이너 들어가기

 

 

 

이미지 생성하기

docker create -it --name (이름) (기본 이미지;centos:latest)

 

 

 

다시 시작하기

docker start 이미지/id

 

 

 

 

 

 

웹서버 돌리기

 

컨테이너 80포트와 호스트 80포트 바인딩 시켜서 돌리기

 

 

 

컨테이너는 휘발성

 

이미지를 만들자.

 

놓침 ㅠㅠ

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

도커 이미지

- 레지스트리에서 관리

 public, private, docker hub 같은대

 

 

 

 

 

wordpress 돌리기'

 

먼저 워드프레스용 db 부터 준비

 

mysql 돌리기, 환경변수도 다음과같이 수행

 

 

docker run -d --name wordpressdb -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=wordpress mysql:5.7 

 

 

 

'

https://hub.docker.com/_/mysql

 

 

wordpress db가 잘돌아가고있다..

 

 

 

 

'

 

 

 

이런식으로 컨테이너에 들어갈수도 있다.

 

docker exec -it wordpressdb /bin/bash

 

 

 

 

wordpress 컨테이너 돌리기

 

 

docker run -d -e WORDPRESS_DB_PASSWORD=password --name wordpress --link wordpressdb:mysql -p 80:80 wordpress 

 

 

 

 

wordpress와 wordpressdb가 잘 동작중..

 

 

 

 

 

 

 

워드프래스 페이지도 잘나온다.

 

 

 

둘다 종료하려면

 

docker rm -f wordpress wordpressdb

 

 

 

종료했다가 다시 실행하면 다날라간다..

 

 

컨테이너 -> 읽고 쓰기 가능

이미지 -> 안변함

 

이미지 추가, 삭제, 변경? => 사실 컨테이너에서 삭제, 추가, 변경됨. 컨테이너는 날라간다

 

컨테이너의 볼륨을 사용하도록 지정??

 

 

 

호스트의 볼륨을 공유 

-v 호스트 경로:컨테이너 경로

=> 호스트의 /home/wordpress_db에서 쓰면 컨테이너의 /var/lib/mysql이 반영

 

 docker run -d --name wordpressdb_hostvolume -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=wordpress -v /home/wordpress_db:/var/lib/mysql mysql:5.7

 

 

- 호스트 경로에 컨테이너의 파일이 공유

 

워드프래스도 돌리자

 

docker run -d -e WORDPRESS_DB_PASSWORD=password --name wordpress_hostname --link wordpressdb_hostvolume:mysql -p 80:80 wordpress

 

 

 

 

설정도 다하고 껏다 키면

 

원래 컨테이너 내용들은 다 사라져야 정상이지만

 

호스트 볼륨에 db를 저장해놔서 껏다 켜도 사라지지 않는다.

 

 

 

 

 

로그 처리보기

 

 docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=1234 mysql:5.7

는 잘실행되지만

 

 docker run -d --name no_password_mysql mysql:5.7

 

비밀번호를 주지않는 경우 ps가 존재하지 않는다.

 

 

docker logs 이름을 주면 로그가 나온다.

 

 

docker logs no_password_mysql을 하면

 

mysql_root_password를 안준게 문제라고 나온다.

 

 

 

 

 

컨테이너 정보보기

 

docker inspect 이름

 

 

 

도커 이미지 숙지하기

 

 

컨테이너는 날라가지만 이미지는 만들수있다.

 

 docker run -it --name commit_test ubuntu:14.04

 

컨테이너에서 파일하나 만들어주고 나오자

 

 

컨테이너는 동작중

 

 

 

 

이미지 만들기

 

docker commit -a "이름" -m "메시지" 컨테이너명 저장소:태그

 

 

 

 

 

 

 

 

과제하기

 

 

2. jupyter/datascience-notebook or jaimeps/rl-gym 등 데이터 사이언스 관련 컨테이너를 public cloud에서 구동하고 jupyter에서 접속한다.

 

 

도커허브에서 풀 커맨드 카피

 

 

 

이미지 다운받고

 

docker pull jupyter/datascience-notebook

 

 

 

 

 

주피터 이미지를 돌리고, 쉘로 들어가서 외부 접속을 허용시켜주자

주피터 설정 파일에 들어가서

 

 

#c.notebookapp.allow_origin="" 는 주석을 지우고 별표

c.notebookapp.allow_origin="*"

 

 

 

 

내가만든 이미지를 확인해보니 ip 주소가 172.17.0.2 이므로

 

8888포트로 들어갈수있도록 방화벽도 오픈하자.

 

 

토큰 안나오개 하려다 망해서 그냥 패스

 

---------------------------------------

 

 

 

 

 

 

 

 

 

 docker run -d -p 8888:8888 -v /home/jupyter:/home/jovyan/work --name juyter jaimeps/rl-gym

 

로그서 토큰보고 들어가자

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3. pytorch를 설치한 이미지로 컨테이너를 구동한다.

 

 정리하기 귀찬다.

 

 

jupyter/datasicn블라블라 컨테이너에들어가서

 

 

 

pip로 torch 설치

 

pip install torch

 

 

 

 

토치 설치된 컨테이너를 이미지로 만들어주자 docker commit

 

* docker commit -a "작성자" -m "메시지" 이미지만들패키지 [저장소명:태그]

docker commit -a "jdo" -m "add torch" jupyter jdo/jupyter:first

 

 

기존의 컨테이너는 지워주고

 

docker rm -f jupyter

 

 

 

 

새로 만든 이미지를 실행하자

 

docker run -d --name jupyter -p 8888:8888 -v /home/jupyter:/home/jovyan jdo/jupyter:first

 

 

주피터 컨테이너에 동작하면, 이 컨테이너의 배쉬 셸로 들어가자

 

docker exec -it jupyter /bin/bash

 

 

python 명령어로 python 인터프리터 실행

 

 

import torch

 

print(torch.__version__)

 

설치된 토치의 버전 확인까지 하면 끝 !

 

 

 

 

 

 

 

 

300x250
728x90

 

 

컴퓨터 개론 introduction to computer science

- 컴퓨터 과학 전반에 대해 소개

-> 자료 구조, 알고리즘, 컴퓨터구조, 운영체제, 네트워크, 프로그래밍 언어 등

 

 

자료 처리기data processor로서의 컴퓨터

- 자료 data를 입력받아 처리 process 후 결과result를 출력

- ex. 계산기

=> 자료를 처리하는 기계만으로 이해하기는 불충분

 

 

프로그램이 가능한 자료 처리기로서의 컴퓨터

- 입력 -> 자료 처리 + 프로그램 -> 출력

 

 

프로그램 program

- 자료를 어떻게 처리할지 정의한 명령 집합

- 프로그래밍 과정의 결과물

-> 기계어 파일, 실행 파일 exe

 

 

 프로그래밍 과정

- 간단하게 코딩이라 부름

- 문제 해결을 위한 흐름(알고리즘)을 정의함

 

 

처리 속도 단위

- ms : 밀리 세컨드 $10^{-3}$초

- $\mu$s : 마이크로 세컨드 $10^{-6}$초

- ns : 나노 세컨드 $10^{-9}$초

- ps : 피코 세컨드 $10^{-12}$초

 

 

 

 

 

 

 

 

컴퓨터 발전 과정

- ~ 1930년 : 기계식 계산기

- 1930 ~ 1950 : 전자식 컴퓨터

 -> 1942, ABC : 선형 방정식 푸는 컴퓨터

 -> 1944, Colossus : 앨런 튜링, 독일 암호 해독

  ****************** 위는 특수 목적용 ************

 -> 1946, ENIAC : 최초 완전 전자식 범용 컴퓨터

                       (외부에서 프로그램이 저장 => 실행 프로그램이 컴퓨터 외부에 존재, 데이터만 내부 저장)

 -> 1950, EDVAC : 내장 프로그램 방식 최초 컴퓨터

                       (컴퓨터 내부에 프로그램이 저장됨)

 

 

 

 

 

 

* 앨런 튜링 : 현대 컴퓨터 고안(튜링 머신),

튜링 머신

- 태잎과 헤드가 존재

- 태잎에 데이터 읽기 쓰기

- 해드를 이동시켜 읽고쓸 태잎을 변경

 

http://www.aistudy.co.kr/computer/turing_machine.htm

 

 

 

 

 

 

 

세대별 컴퓨터 분류

1세대 1950 ~ 1959

- 진공관

 

2세대 1959 ~ 1965

- 트랜지스터

- 포트란, 코볼

 

3세대 1965 ~ 1975

- 집적회로

- SW 등작

 

4세대 1975 ~ 1985

- 초고밀도집적회로

- 마이크로 컴퓨터 등장 8800

- 네트워크 

 

5세대 1985 ~

- 현재

 

 

 

 

 

 

 

 

 

 

컴퓨터 분류

1. 컴퓨터 사용 목적에 따른 분류

- 범용 컴퓨터

- 전용 컴퓨터

 

2. 자료 표현 방식

- 디지털 컴퓨터 : 이산적인 값을 처리

- 아날로그 컴퓨터 : 연속적인 입력양을 그대로 사용

 

3. 성능에 따른 분류

- 슈퍼 컴퓨터

- 대형 컴퓨터

- 미니 컴퓨터

- 워크 스테이션

- 마이크로 컴퓨터

 

 

 

 

 

 

 

컴퓨터 과학이란? 

- 컴퓨터 제작하는 학문 ..?

- 프로그램 개발하는 학문 ..?

=> 컴퓨터를 이용하여 데이터를 통해 다양한 문제와 방법들을 다루는 학문

 

 

프로그램과 알고리즘

- 컴퓨터는 자료를 처리해서 결과(정보)를 얻는 기계

-> 문제를 해결하기 위한 명령어 집합인 프로그램을 사용

-> 알고리즘 : 문제 해결을 위한 흐름 -> 프로그램

 

 

 

관련 학문

- 자료 : 자료구조, 파일처리, 데이터베이스

- 정보 : 컴퓨터 시스템, 디지털 논리구조, 컴퓨터 구조

- 프로그램 : 운영체제, 컴파일러, 프로그래밍언어 ,정보통신, 컴퓨터그래픽스

- 알고리즘 : 이산구조, 계산이론, 인공지능, 알고리즘, 오토마타

=> 전반적인 분야를 파악해야함

 

 

 

 

 

 

컴퓨터 공학 computer engineering과 컴퓨터 과학computer science의 차이

- 컴퓨터 공학 engineering : 가성비 좋은 제품을 만들기 위해 HW와 SW 조합에 초점

- 컴퓨터 과학 science : 문제 해결의 효율성과 실현 가능성에 초점

 

 

 

 

시스템 system

- 원하는 목적을 달성하기 위해 여러가지 요소들이 모여 연결된 체계

 

HW 하드웨어 : 눈으로 볼수있는 장치로 물리적 기계 및 전자장치

 

 

폰 노이만 구조와 하버드 구조

- 컴퓨터 내부 구조, 처리 과정을 정의한 것

- 컴퓨터 구조는 대표적으로 폰노이만 구조와 하버드 구조가 있음

- 대부분은 폰 노이만 구조를 채택

- 데이터 버스와 명령어 버스가 통합 -> 폰노이만 구조

- 데이터 버스와 명령어 버스가 분리됨 -> 하버드 구조

 

 

 

 

 

4개의 서브시스템

기억 장치

- 데이터와 명령어(프로그램)을 저장하는 곳

-> 주기억 장치(RAM, ROM), 보조기억장치(HDD, SSD)

 

산술논리연산장치 ALU

- 데이터 산술(+-*/), 논리(and, or)연산하는 장치

 

제어 장치 Control Unit

- 기억장치, ALU, 입출력 장치 등 동작 제어

=> CPU = ALU + CU + Register

 

 

입출력 장치 I/O Device

- 입력 : 키보드, 마우스, 마이크

- 출력 : 모니터, 프린터, 스피커 

 

 

 

 

내장 프로그램 stored program

- 실행될 프로그램은 메모리에 저장 stored or 적재 load 되어야 함

- 프로그램과 데이터는 비트 패턴으로 메모리 상에 표현

 

 

자료와 정보

- I = P(D)

- I는 정보

- P는 처리

- D는 자료

- 자료D를 처리P하여 정보 I를 취득

 

 

 

자료의 형태

- 문자, 숫자, 이미지, 오디오, 비디오 등

=> 다 비트로 표현

 

 

 

 

 

 

 

 

 

 

 

 

 

 

자료 단위

- 비트 binary digit : 0과 1을 표현

- 바이트 byte : 비트 8개

- 킬로 바이트 KB kilo byte : 바이트 $2^10$

- MB 메가바이트, GB기가바이트, TB테라바이트, PB페타바이트

- 워드 word : 컴퓨터 연산의 기본 단위가 되는 정보 양 -> 32비트, 64비트

 

 

 

진법 number system

- 수를 세는 단위

- 2, 8, 10, 16진법

- 2진법은 읽거나 오류 찾기 힘듬

-> 8진법, 16진법 사용

- 010 : 8진법으로 2

 * 앞에 0이 붙으면 8진법 수

- 0x0a : 16진법으로 10

 * 앞에 0x가 붙으면 16진법수

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

300x250

'컴퓨터과학 > 컴퓨터, OS' 카테고리의 다른 글

HWSW - 2. 컴파일  (0) 2020.08.06
HWSW - 1. MCU  (0) 2020.08.05
os만들기 - 25. GDT와 IDT 다루기  (0) 2020.08.04
os만들기 - 24. 변수 표시하고, 마우스 띄우기  (0) 2020.08.03
os만들기 - 23. 문자(열) 처리  (0) 2020.08.03
728x90

* 라즈베리파이3, stretch

 

라즈베리파이를 설치할때마다

 

잘 모르는 경우 별도로 모니터를 준비해서 사용하곤 합니다.

 

그나마 한글로는 ssh 접속에 대한 자료들은 있지만

 

 

 

 

 

sd카드에 파이 이미지를 굽고 나서

 

화면도 없고, 인터넷도 연결못하는 상태에서 어떻게 하는지에 대해서

 

우리나라에는 자료가 잘 없는것같습니다.

 

 

 

다음 자료들을 참고하여 작성하였습니다.

 

 

화면 없이 ssh 사용가능하게 하기

ref : https://howchoo.com/g/ote0ywmzywj/how-to-enable-ssh-on-raspbian-without-a-screen

 

이더넷 케이블없이 와이파이 접속되도록 설정하기

ref : https://howchoo.com/g/ndy1zte2yjn/how-to-set-up-wifi-on-your-raspberry-pi-without-ethernet

 

boot(드라이브)의 ssh와 wpa_supplicant.conf 파일이 계속 삭제됩니다

ref : https://raspberrypi.stackexchange.com/questions/85441/ssh-and-wpa-supplicant-conf-files-not-getting-deleted-on-boot

 

 

 

 

 

 

일단 저는 라즈비안 strech로 이미지를 우선 구웠습니다.

 

 

 

 

 

ssh 허용하기

- boot 드라이브(sd카드)에 이름이 ssh인 빈 파일을 만들어 주면 됩니다.

 

 

 

화면 없이 wifi 접속 시키기

1. 연결할 엑세스 포인트(공유기나 핫스팟)에 대한 정보를 wpa_supplicant.conf 파일을 만들어 적어주고

 

 

country=US
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
    ssid="placeholder"
    psk="placeholder"
    scan_ssid=1
    key_mgmt=WPA-PSK
}

 

2. boot 드라이브(sd카드)에 넣으면 끝

 

 

 

* ssh 파일과 wpa_supplicant.conf를 만들었는데 연결은 안되고 이 파일들이 사라지는 경우

1. wpa_supplicant.conf 파일에서 액새스 포인트 정보를 잘못 입력한 경우

2. scan_ssid=1을 추가하여 한번 와이파이 스캔을 해주면 될것 같습니다.

 

 https://raspberrypi.stackexchange.com/questions/85441/ssh-and-wpa-supplicant-conf-files-not-getting-deleted-on-boot

 

 

 

 

 

 

이제 와이파이가 핫스팟(혹은 공유기)에 연결되었으면

 

ssh로 접속하면 됩니다.

 

디폴트 기본 아이디 및 비번 :  pi/raspberry

 

 

 

공유기는 공유기 설정 화면에서 접속한 장치들을 볼수 있지만

 

핫스팟은 어느 아이피로 접속한지 알수 없으니

 

지난번에 zumi에서 했던것 처럼 nmap으로 wifi 대역을 스캔해줍시다.

 

ref : throwexception.tistory.com/871

 

 

라즈베리파이가 할당받은 아이피 주소도 확인했으니 바로 ssh 접속

 

 

 

 

 

잘 접속 되었으니 이제 화면도 써야되겠죠.

 

vnc 설정도 enable해줍시다.

 

ref : throwexception.tistory.com/872

 

 

 

접속한 화면

 

이미 라즈베리파이4가 나온지 조금 됬지만

 

파이 제로만 사용하다가 파이3을 쓰니 날라간다

 

300x250
728x90

ref : https://matplotlib.org/api/_as_gen/matplotlib.pyplot.subplots.html

 

 

 

1. 1 x 2 열 subplot

 

 

import numpy as np
import matplotlib.pyplot as plt

# First create some toy data:
x = np.linspace(0, 2*np.pi, 400)
y = np.sin(x**2)

# Create two subplots and unpack the output array immediately
f, (ax1, ax2) = plt.subplots(1, 2, sharey=True)
ax1.plot(x, y)
ax1.set_title('Sharing Y axis')
ax2.scatter(x, y)

plt.show()

 

 

2. 2x2 서브플롯 생성

 

 

import numpy as np
import matplotlib.pyplot as plt

# First create some toy data:
x = np.linspace(0, 2*np.pi, 400)
y = np.sin(x**2)

# Create four4 axes and access them through the returned array
fig, axs = plt.subplots(2, 2)
axs[0, 0].plot(x, y)
axs[1, 1].scatter(x, y)

plt.show()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

300x250
728x90

가장 단순한 plt.subplots()

 

여러개 플롯 생성 없이 사용.

 

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2*np.pi, 400)
y = np.sin(x**2)

# Create just a figure and only one subplot
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_title('Simple plot')

plt.show()

300x250
728x90

컴파일러와 리버스 컴파일러

- 컴파일러 : 소스 코드 -> 기계어

- 리버스 컴파일러 : 기계어 -> 어셈블러/소스코드

 

 

인터프리터와 컴파일러

- 인터프리터 : 소스코드 한줄 씩 즉시 실행

- 기계어 : 소스코드 전체 기계어로 변환 후 실행

 

 

컴파일러 도구 정리

- 컴파일러 : 소스 코드 -> 어셈블리어

- 어셈블러 : 어셈블리어 -> 기계어(오브젝트 파일)

- 링커 : 오브젝트 파일들을 연결시켜 하나의 실행 가능한 파일(기계어) 생성

 

 

MCU와 고급언어

- 고급언어로 작성한 소스코드는 컴파일러에의해 어셈블리어로 변환, 이후 어셈블러로 각 MCU에 맞는 기계어로 변환됨

- ARM 어셈블리어 -> ARM 기계어

- AVR 어셈블리어 -> AVR 기계어

- x86 어셈블리어 -> X86기계어

 

 

기계어, 어셈블리어

- 기계어 : 0과 1로 이루어진 바이너리 코드

- 어셈블리어 : 기계어와 사람이 이해할 수 있는 명령어를 매칭시켜 만든 언어

- 아래의 그림은 고급언어, 어셈블리어, 기계어 사이 차이를 보여주고 있음

https://asecurity.dev/2017/07/%EC%97%AD%EB%B6%84%EC%84%9D-%EA%B8%B0%EA%B3%84%EC%96%B4%EB%A5%BC-%EB%B6%84%EC%84%9D%ED%95%9C%EB%8B%A4-disassemblers/

 

 

 

ARM 명령어 집합과 포멧

- ARM은 고정 크기와 형식을 갖는 명령어 사용. 아래의 그림은 32비트 고정 길이 명령어 집합을 보여줌.

- 아래와 같은 포멧으로 요소별 의미를 이해하여 올바른 값을 주면 곱샘, 인터럽트 등 기능 수행

https://damduc.tistory.com/115

- 좌측은 ARM 기계어 명령어, 우측은 디스어셈블한 어셈블리어 코드

http://www.jkelec.co.kr/img/lecture/arm_arch/arm_arch_4.html

 

 

 

명령어 처리기와 기계어

- 명령어 처리기가 해석하는 방식에 다라 기계어 코드가 달라야 함

 => 동일한 기계어 코드도 명령어 처리기가 다르면 다르게 해석

- 대표적인 명령어 처리기 구조 : RISC와 CISC

 

 

RISC와 CISC

- RISC Reduced Instruction Set Computer

  리스크. 축약된 명령어 집합. 적은 수의 명령어들만 제공 -> 단순구조, 고속

           => RISC 명령어 셋을 가진 경우. RISC머신(대표적으로 ARM)

- CISC Complex Instruction Set Computer

   씨스크. 복잡한 명령어 집합. 수많은 명령어들 제공 ->복잡구조, 저속 

          => CISC 명령어 셋을 가진 경우. CISC 머신(대표적으로 x86)

- 곱셈 연산에서의 리스크와 씨스크의 차이

 -> CISC는 mul 명령어로 곱샘 수행. RISC는 값들을 레지스터에 담은 후 반복문 수행

 -> CISC가 단순하다

 

 

 

통합 개발환경

- GUI 환경에서 개발을 편리하게 할수록 도와주는 도구

- 텍스트 에디터(소스 편집기)

- 빌드 도구 : 컴파일러, 어셈블러, 링커

- 디버거 : 실제 MCU를 동작시키며 MCU 변수, 레지스터 등의 상태 변화 학인

- 에뮬레이터 : MCU와 개발 환경을 연결시켜줌

- 시뮬레이터 : 가상의 기계와 개발 환경을 연결시킴

 

 

 

 

 

 

 

 

 

컴파일 과정

1. 전처리 preprocessing

- c언어에서 #define이나 #include 명령어들이 존재 

 => #define은 해당 단어 치환하고, #include는 관련 해더파일 복붙

 

2. 낱말 분석 lexical analysis

- 어셈블리어는 명령어와 데이터만으로 구성 => C언어도 명령어와 데이터로 구분하자

 => 몇개의 데이터, 명령어 등이 필요한지 알 수 있음.

- 아래의 그림은 낱말 분석 입력 예시

- 낱말 분석의 결과 아래와 같이 지시자, 식별자, 연산자, 값 등으로 정리됨

https://www.youtube.com/watch?v=edZfw9Yp7h4

 

3. 코드 최적화 code optimization

- 실행 공간을 절약하거나, 사용하지 않는 변수 제거하는 등 작업 수행

- 아래의 그림은 공간 낭비를 줄여주는 최적화 예시

https://atadiat.com/en/e-application-note-tips-tricks-optimize-c-code/

 

 

4. 메모리 테이블화 (심볼 테이블)

- 코드에 존재하는 변수들을 읽고 저장하기 위해 메모리 필요. -> 메모리 주소와 변수 명을 연결

 => 심볼 테이블 작성 : 해당 변수가 어느 메모리를 사용하는가?

- 심볼 테이블은 변수들을 ID로 관리. 변수들은 고유의 수납장 번호(이름을 갖고 있음)

 

https://victorydntmd.tistory.com/241

 

 

5. 구문 분석 syntax analysis

- 구문 syntax의 의미 : 단어들이 모여서 만든 의미

 => 코드가 언어의 문법을 따르는지 분석. 구문 나무 syntax tree 사용

- 구문 나무 사용 이유 : 명령어와 변수 구분이 편하고, 어셈블리어로 변환이 쉬움

- 아래의 그림은 구문 나무를 이용하여 명령어와 데이터 정리 형태를 보여줌

http://chirucprogvideos.blogspot.com/2015/06/compiler-and-interpreter.html

 

- 단어 분석과 구문분석의 결과 예시

https://homoefficio.github.io/2019/01/31/Back-to-the-Essence-Java-%EC%BB%B4%ED%8C%8C%EC%9D%BC%EC%97%90%EC%84%9C-%EC%8B%A4%ED%96%89%EA%B9%8C%EC%A7%80-1/

 

 

 

6. 어셈블리어 명령어 치환

- 구문 분석과정에서 명령어와 데이터가 구분됨

 => 데이터는 심볼테이블 ID(주소), 명령어는 어셈블러로 치환하자

 

7. 어셈블리어 완성

- 데이터들을 실제 메모리로 할당

 

8. 완성된 어셈블리어로 기계어 생성

- 어셈블리를 이용해서 기계어 작성

https://www.slideserve.com/barny/assembly-machine-language

 

300x250
728x90

MCU Micro Controller Unit

- 전자제품에사용되는 제어 유닛

- 주위 주변장치 GPIO, UART 등 제어함

- CPU보다 저전력, 저성능, 저럼, 많이사용

- 구성 : 메모리, 레지스터, 페리페럴, 버스 등으로 구성

참고 : https://www.hackerschool.org/Sub_Html/HS_University/HardwareHacking/04.html

 

 

 

PCB Printed Circuit Board

- 녹색 전자 회로 기판

- 이 위에 MCU와 다른 전자 소자 등이 올라감

 

https://en.wikipedia.org/wiki/Printed_circuit_board

 

 

IC Integrated Circuit

- 집적화된 회로

- 전자 부품, 소자들을 모아 하나의 회로에 집적화한것

- 아래의 그림은 IC칩의 패키지들. IC칩 내부 소자들을 보호하기 위한 플라스틱 케이스

 

http://blog.daum.net/go_ahead/14

- 아래의 그림은 다이칩 die chip : 실제 패키지 내부 IC

https://metallux.ch/hybridcircuit/chip-on-board-cob/

 

 

 

 

MCU 내부 장치

1. 버스

- 메모리, 페리페럴, CPU 사이 데이터 주고받기위한 공용 통로.

- Control bus 제어버스, Address bus 주소버스, Data bus 데이터버스 등 존재

- MCU가 제어 명령, 주소, 데이터 등을 전송시키는 시간을 조절하여 데이터간 충돌을 회피

 

https://www.renesas.com/us/en/support/technical-resources/engineer-school/mcu-programming-peripherals-01-gpio.html

 

2. 메모리

- 기억 장치. 휘발성 비휘발성에따라 RAM과 ROM으로 구분

- 휘발성 : 전원이 없을때 데이터가 날아감 -> RAM

- 비휘발성 : 전원이 없을때 데이터 보존 -> ROM

 

2.1 ROM Read Only Memory의 종류

 - PROM Programmable ROM - 프로그래밍 가능한 메모리. 한번만 쓰기가능

 - EPROM Erasable Programmable ROM - 자외선으로 쓰고 지우는게 가능한 PROM

 - EEPROM Electric EPROM : 전기적 충격으로 쓰기 읽기가 가능한 ROM

        => 대표적인 EEPROM으로 Flash Memory가 존재

 

2.2 RAM Random Access Memory

 - SRAM, DRAM, SDRAM이 존재

 - SRAM Static Random Access Moery

      -> 트랜지스터만으로 만든 메모리, 고속, 고가 소형화 힘듬 

 - DRAM Dynamic RAM

      -> 캐퍼스터와 트랜지스터로 구성된 메모리                        

      ->  캐퍼시터를 사용한 만큼 데이터 손실을 막기위해 충전하는 Refresh Time 필요. 저가

 - SDRAM Synchronous DRAM

    -> 동기식 메모리. 외부에서 공급해주는 클럭에 따라 동기화

    -> 클럭 신호선이 존재하여 데이터 처리 시 지연시간 latency 필요

 - 아래의 그림은 SRAM의 소자

https://ko.wikipedia.org/wiki/%EC%A0%95%EC%A0%81_%EB%9E%A8

 

 

 

3. 메모리맵

- 대부분의 MCU의 데이터 시트에서 제공하는 정보로 할당된 각 메모리의 주소와 용량을 알 수 있음.

- 아래은 하드웨어 구성을 위한 메모리맵으로 SRAM 영역이 0x2000 0000 ~ 0x3FFF FFFF임을 알 수 있음

 

https://todayis.tistory.com/tag/%EB%A9%94%EB%AA%A8%EB%A6%AC%EB%A7%B5

 

- 아래의 그림은 소프트웨어적으로 분리된 메모리 맵

 스택 영역 stack : 지역변수, 함수 포인터

 힙 영역 heap : 동적 할당된 메모리 공간

 코드 영역 code : 명령어 등이 저장됨

 데이터 영역 data : 전역 변수들이 저장

https://ko.wikipedia.org/wiki/%EB%A9%94%EB%AA%A8%EB%A6%AC_%EB%A7%B5

 

 

4. 레지스터 register

- MCU 내부에 존재하는 가장 빠른 메모리. 비싸 페리페럴이나 CPU 내부에 작은 공간을 가짐

- 프로그램 카운터 PC Program Counter, 스택 포인터 SP Stack Pointer, 명령 레지스터 IR Instruction Register, 데이터 레지스터 DR Data Register, AR Address Register, 범용 레지스터 General Register 등 존재

 

4.1 레지스터 종류

- 프로그램 카운터 : 다음에 실행할 명령어의 주소를 저장하는 레지스터

 * 아래의 그림은 프로그램의 실행과정으로 여기서 프로그램 카운터가 다음에 실행할 명령어 주소를 가지고 있음

   => 프로그램 카운터의 값이 실행할 명령어 위치가 되어 찾아감

      다음 프로그램 카운터값은 명령어 크기만큼 +됨.

      32비트 컴퓨터 즉, 4바이트 크기라면 0x0000 -> 0x0004 -> 0x0008

https://kasckasc.tistory.com/entry/2-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%98-%EC%8B%A4%ED%96%89-%EA%B3%BC%EC%A0%95-%EB%B0%8F-CPU-%EA%B5%AC%EC%A1%B0%EC%99%80-%EC%9B%90%EB%A6%AC

- 스택 포인터

   -> 함수 호출과 관련된 정보들을 스택 자료구조로 저장하는 공간.

   -> 함수가 호출되고 종료후 돌아갈 지점과 데이터들을 관리

 

 

http://www.tcpschool.com/c/c_memory_stackframe

 

- 명령어 레지스터 : 명령어들을 담는 레지스터

- 데이터 레지스터 : 데이터들을 담는 레지스터

- 범용 레지스터 : 프로그램 카운터, 스택 포인터, 명령/데이터 레지스터 제외한 범용 목적의 레지스터

 

 

 

5. 메모리 관리 유닛 MMU Memory Management Unit

MMU

- 메모리 공간에 프로그램을 로드하여 사용중에 충돌이나 문제를 막기위한 HW.

  * 동일한 문제를 막기위한 SW로 OS가 있음.

 

MMU 기능과 구성 요소

- 기능 : 가상 메모리 Virtual Memory와 실제 Physical memory 사이 변환 및 메모리 보호

- 가상 메모리 : 가상의 메모리로 물리적인 메모리보다 큼

- 물리 메모리 : 실제 존재 존재하는 메모리

 

가상 메모리, MMU를 사용하는 이유

- 소프트웨어는 자신이 사용할 공간을 자기가 고르지 못하고 메모리 관리를 위해 운영체제가 배정해줌

- 프로그램들은 가상 메모리의 0x0000 0000에서 시작하지만 실제로 MMU가 물리 메모리의 주소로 변환해줌

- 여러 프로그램들이 초기 지점인 0x0000 0000에서 시작하고, 물리 메모리 상에서 겹쳐지지 않게 하기 위함

 

https://awesomebit.tistory.com/22

 

 

6. 캐시 메모리

캐시 메모리

- CPU는 매우 빠르게 동작하지만, 메모리는 CPU에 비해서 상대적으로 느림

- 중간에 데이터를 미리 모아놓기 위한 공간으로 캐시메모리 사용.

- 캐시메모리는 레지스터보다 크나 메모리에 보다 매우 작음

- 아래의 그림은 CPU와 캐시 메모리, 메모리 사이의 구조를 보여줌

https://m.blog.naver.com/PostView.nhn?blogId=remocon33&logNo=220129153263&proxyReferer=https%3A%2F%2Fwww.google.com%2F

 

 

 

7. 페리페럴 Peripheral

페리페럴

- MCU 내부에 존재하는 주변장치들, 주변장치들을 사용하기 위한 단자

- 대표적으로 통신 페리페럴로 UART, SPI, I2C 등이 존재

- 아래의 그림은 페리페럴들의 예시

https://www.renesas.com/us/en/support/technical-resources/engineer-school/mcu-programming-peripherals-01-gpio.html

 

UART Universal Asychronous Receive Transmiter

- 범용 비동기 수신 발신기로 송신용 Tx와 수신용 Rx 신호선 2개로 구성됨

- 비동기 인 만큼 클럭에 상관없이 통신은 가능

- 아래의 그림은 UART 통신 시 연결

https://www.weekitech.com/2019/05/13/introduction-to-uart/

- 아래의 그림은 UART 통신시 데이터 프레임(형태)

https://m.blog.naver.com/PostView.nhn?blogId=1992cjm&logNo=220438189832&proxyReferer=https:%2F%2Fwww.google.com%2F

 

 

 

RS-232

- 비동기 통신 중 길이와 속도를 맞추기 위해 RS-232라는 표준이 제정됨

 => RS-232로 특정 규칙에 따라 UART 통신이 안정적으로 수행됨

- 아래의 그림은 RS-232 핀아웃 별 의미

http://raspberrypi.tomasgreno.cz/uart-to-rs-232.html

 

- 아래의 그림은 RS-232 통신 시 데이터 프레임

https://qastack.kr/electronics/110478/difference-between-uart-and-rs-232

 

 

 

 

명령어 실행과정

- 명령어 실행 사이클이라도 함

- 메모리에서 명령어를 가져오고 fetch, 명령어를 해독 후 decode, 실행 excution하는 과정

https://kasckasc.tistory.com/entry/2-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%98-%EC%8B%A4%ED%96%89-%EA%B3%BC%EC%A0%95-%EB%B0%8F-CPU-%EA%B5%AC%EC%A1%B0%EC%99%80-%EC%9B%90%EB%A6%AC

 

 

 

 

파이프라인

파이프라인 구조

- 명령어 실행 과정으로,  패치 -> 해석 -> 실행 -> 저장 으로 정리할 수 있음

- 이를 고속으로 하기 위한 구조를 파이프라인. 

 

파이프라인과 싱글라인의 차이

- 기존의 싱글 라인 구조는 하나의 명령어가 종료될때까지 다음 명령어가 대기

- 파이프라인 구조에서는 첫 명령어가 다음 단계로 넘어가면 새로운 명령어가 들어와 여러 명령어가 동시 수행

- 아래의 그림은 파이프라인 구조 예시

https://doitnow-man.tistory.com/72

 

 

 

인터럽트

인터럽트란

- 프로그램 수행시 중간에 처리해야하는 상황과 동작 -> 예외처리/인터럽트라 부름

- 인터럽트 발생시 인터럽트 종류에 따라(인터럽트 벡터 테이블을 참고하여) 정해진 명령으로 PC의 값이 변경됨

- 아래의 그림은 인터럽트 벡터 테이블로 인터럽트 종류에 따라 수행해야할 동작들의 주소를 알려줌

 

https://blog.naver.com/seim_ryu/110020336124

 

인터럽트 관련 용어

- 인터럽트 벡터 :인터럽트를 처리하기위한 PC값으로 벡터 테이블에서 프로그램 카운터 값을 가져옴

- 인터럽트 핸들러 ISR Interrupt Service Routine : 인터럽트 발생시 처리해야할 콜백 함수

- 아래의 그림은 인터럽트 처리 과정

을 보여줌

https://m.blog.naver.com/PostView.nhn?blogId=scw0531&logNo=220650635893&proxyReferer=https:%2F%2Fwww.google.com%2F

 

 

 

 

 

 

 

300x250

+ Recent posts